Android - 屏幕适配,Application,全局捕获异常,Build类,广告平台,应用的混淆

本文介绍了Android应用开发中的关键技巧,包括屏幕适配方法、Application类的应用、全局异常捕获、Build类信息提取、广告平台选择及应用混淆策略等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明出处:https://blog.youkuaiyun.com/mythmayor/article/details/72900565

1.屏幕适配

  1. 使用LinearLayout、RelativeLayout、FrameLayout
  2. 单位使用dp、dip、sp
  3. 代码中使用dip、sp等单位

    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
    

2.应用的Application

Appication:代表这个应用程序。对应AndroidManifest.xml的<application>节点,创建后需要在清单文件中进行配置。

单例,可以保存全局变量进行数据传递。APK加载内存中后的第一个实例化对象。onCreate方法的执行优先于activity和service和receiver的实例创建(除了ContentProvider),可执行不耗时的初始化操作。service和activity可通过getApplication()获取到实例对象。

3.全局捕获异常

public class projectApplication extends Application {
    //应用程序创建之前执行的第一个方法
    //适合做应用程序的初始化操作
    @Override
    public void onCreate() {
        //重写系统的异常处理器
        super.onCreate();
        Thread.currentThread().setUncaughtExceptionHandler(new MyExceptionHandler());
    }


    private class MyExceptionHandler implements UncaughtExceptionHandler{
        //当发现了未捕获异常的时候调用的方法
        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            System.out.println("发生了异常,但是被哥捕获了。。。");
            //自杀的方法. 早死早超生
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }
}

4.Build类

提取设备硬件和版本信息

内部类:  
1、Build.VERSION 版本相关常量字符串  
2、Build.VERSION_CODES 目前已知的版本代码的常量类

静态属性  
1、BOARD 主板:The name of the underlying board, like goldfish.  
2、BOOTLOADER 系统启动程序版本号:The system bootloader version number.  
3、BRAND 系统定制商:The consumer-visible brand with which the product/hardware will be associated, if any.  
4、CPU\_ABI cpu指令集:The name of the instruction set (CPU type + ABI convention) of native code.  
5、CPU\_ABI2 cpu指令集2:The name of the second instruction set (CPU type + ABI convention) of native code.  
6、DEVICE 设备参数:The name of the industrial design.  
7、DISPLAY 显示屏参数:A build ID string meant for displaying to the user  
8、FINGERPRINT 唯一识别码:A string that uniquely identifies this build. Do not attempt to parse this value.  
9、HARDWARE 硬件名称:The name of the hardware (from the kernel command line or /proc).  
10、HOST  
11、ID 修订版本列表:Either a changelist number, or a label like M4-rc20.  
12、MANUFACTURER 硬件制造商:The manufacturer of the product/hardware.  
13、MODEL 版本即最终用户可见的名称:The end-user-visible name for the end product.  
14、PRODUCT 整个产品的名称:The name of the overall product.  
15、RADIO 无线电固件版本:The radio firmware version number. 在API14后已过时。使用 getRadioVersion()代替。  
16、SERIAL 硬件序列号:A hardware serial number, if available. Alphanumeric only, case-insensitive.  
17、TAGS 描述build的标签,如未签名,debug等等。:Comma-separated tags describing the build, like unsigned,debug.

5.广告平台

国外:
StartAPP:http://www.startapp.com/

Google:http://www.google.cn/admob/

国内:

百度:http://app.baidu.com/index/appx

友盟,有米,万普等等

6.应用的混淆

  • project.properties里配置proguard.config=proguard-android.txt
  • 默认的混淆配置文件:sdk\tools\proguard\proguard-android.txt

注意事项:

  • release版本才会混淆
  • 四大组件,自定义View,还有一些其他保证完整性的代码不能混淆

混淆的优点:

  • 降低别人反编译代码的可读性
  • 压缩apk体积。

混淆的缺点:

  • 混淆配置错误导致debug版本没有而release才有的bug不易发现。
  • 运行时代码为混淆过的,降低了错误日志的可读性
<think>好的,我现在需要解决用户的问题:在Android中如何监听全屏的点击事件,包括对话框。用户提到他们知道某个引用,但看起来那个引用是关于Activiti引擎的被移除,可能与Android无关,可能是个错误或者用户混淆了内容。不过先不管这个,专注于Android的问题。 首先,用户想要监听整个屏幕的点击,包括对话框。通常,对话框是覆盖在Activity之上的视图,所以常规的Activity的dispatchTouchEvent可能无法捕获对话框上的点击,因为对话框属于Window,位于不同的层级。 我需要考虑如何监听所有触摸事件,不管是在Activity还是对话框上。可能的思路是使用Application级别的触摸监听,或者通过注册一个全局的触摸监听器。 在Android中,可以通过Activity的getWindow().getDecorView()来获取根视图,然后在上面设置OnTouchListener。不过,对于对话框,特别是使用AlertDialog或者DialogFragment创建的,它们的视图会被添加到WindowManager中,属于不同的Window。这时候,可能需要更全局的监听方式。 另外,可以考虑使用AccessibilityService,但这需要用户授权,可能不太适合普通应用。或者,使用WindowManager添加一个覆盖层,监听所有触摸事件,但这样需要处理权限问题,比如SYSTEM_ALERT_WINDOW权限,这在较新的Android版本中可能需要用户手动授权,不太友好。 另一种方法是,在显示对话框的时候,主动给对话框的根视图添加触摸监听。例如,当创建一个AlertDialog时,在调用show()之后,可以获取其Window的DecorView,并设置OnTouchListener。但这种方法需要每个对话框都手动处理,不够自动化。 有没有办法在应用级别监听所有触摸事件?比如,在每个Activity的onCreate中,或者通过基Activity,统一为DecorView设置触摸监听。但DecorView的触摸事件可能不会传递到Activity的dispatchTouchEvent中,如果对话框的视图是另一个Window的话。 可能正确的做法是,使用Activity的dispatchTouchEvent方法,但这只能捕获该Activity窗口内的事件,而对话框可能属于另一个Window,因此无法捕获。 这时候可能需要更高级的方法。比如,每个对话框显示时,它的视图会被添加到WindowManager中,作为应用级别的窗口。是否可以监听应用内所有窗口的视图添加事件,并在其视图上设置触摸监听? 或者,使用Application.ActivityLifecycleCallbacks来监听所有Activity的生命周期,然后在每个Activity的onResume中为其DecorView添加触摸监听,同时监控Dialog的显示,并为它们的视图添加监听。不过对于Dialog,可能需要hook它们的显示过程,或者在创建Dialog时自动添加监听器。 或者,考虑使用一个透明的View覆盖在整个屏幕上,通过WindowManager添加,这个View可以拦截所有触摸事件。不过需要处理点击穿透的问题,或者将事件传递给下方的视图。 比如,可以创建一个覆盖层View,设置它的onTouchEvent返回false,这样事件会传递给下层,同时在这个View中监听事件。不过这种方法需要权限,并且可能影响其他触摸操作。 具体步骤可能如下: 1. 使用WindowManager添加一个覆盖层View,覆盖整个屏幕。 2. 这个View的布局参数设置为TYPE_APPLICATION_OVERLAY(需要权限)。 3. 在覆盖层View的onTouchEvent中记录事件,然后返回false,让事件继续传递下去。 4. 这样,所有触摸事件都会被这个覆盖层捕获,同时不影响原有操作。 不过,这种方法需要处理权限,并且在Android 6.0(API 23)及以上版本中,SYSTEM_ALERT_WINDOW权限需要用户手动授予,这可能对用户体验造成影响。 另外,对于对话框内的点击,当对话框显示时,它的视图层级可能位于Activity的视图之上,但覆盖层如果是TYPE_APPLICATION_OVERLAY的话,可能会位于对话框的视图之上,因此能够捕获到事件。但需要测试确认。 另一种可能的解决方案是,为每个新显示的窗口(如对话框)动态添加触摸监听。这可能需要反射或者观察WindowManager的视图添加情况,但这种方法可能不够稳定,因为不同系统版本可能有差异。 或者,使用ViewTreeObserver.OnGlobalLayoutListener来监测视图树的变化,当检测到对话框的根视图出现时,为其添加触摸监听。例如,当Activity的DecorView布局变化时,检查是否有对话框的视图出现。 不过,这可能比较复杂,而且不一定可靠。 回到用户的问题,他们希望监听包括对话框的全屏点击事件。可能最直接有效的方法是使用WindowManager添加覆盖层,同时处理权限问题。 现在,我需要整理出步骤,如何在代码中实现这一点。 首先,检查并请求SYSTEM_ALERT_WINDOW权限。然后在代码中创建覆盖View: 创建布局参数: ```java WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT); ``` 创建View并设置OnTouchListener: ```java View overlayView = new View(context); overlayView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // 处理点击事件 return false; // 让事件继续传递 } }); ``` 然后,将View添加到WindowManager: ```java WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); windowManager.addView(overlayView, params); ``` 注意,从Android 8.0(API 26)开始,TYPE_APPLICATION_OVERLAY需要动态请求权限,并且用户必须在设置中手动开启。应用需要在Manifest中添加权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 在代码中,需要检查是否有权限,并引导用户开启: ```java if (!Settings.canDrawOverlays(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, REQUEST_CODE); } ``` 用户可能不希望处理这样的权限请求,所以这可能不是最优解。有没有其他方法? 或者,对于应用内的对话框,可以在显示对话框时主动为其根视图添加触摸监听。例如,当使用AlertDialog.Builder创建对话框时,在show()之后获取其Window的DecorView,并设置监听: ```java AlertDialog dialog = new AlertDialog.Builder(context).create(); dialog.show(); View decorView = dialog.getWindow().getDecorView(); decorView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // 处理点击事件 return false; } }); ``` 但这种方法需要为每个对话框手动添加监听,不够自动化。如果应用中有很多地方创建对话框,这会导致重复代码。 有没有办法统一处理所有对话框的创建?例如,通过继承Dialog,或者在基中重写显示对话框的方法。或者使用DialogInterface.OnShowListener来捕获对话框显示事件,然后为其根视图添加监听。 例如,使用Dialog的setOnShowListener: ```java AlertDialog dialog = new AlertDialog.Builder(context).create(); dialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialogInterface) { View decorView = ((AlertDialog) dialogInterface).getWindow().getDecorView(); decorView.setOnTouchListener(...); } }); dialog.show(); ``` 这可以在对话框显示时自动添加监听。如果应用使用统一的对话框创建方式,可能可以封装这个方法。不过,如果应用中有多种对话框创建方式,可能需要统一处理。 此外,对于Activity本身的触摸事件,可以通过在Activity的dispatchTouchEvent方法中处理: ```java @Override public boolean dispatchTouchEvent(MotionEvent ev) { // 处理事件 return super.dispatchTouchEvent(ev); } ``` 但这种方法只能捕获Activity窗口内的事件,而对话框可能属于另一个窗口,因此无法捕获对话框上的事件。 综合以上分析,可能的解决方案有两种: 1. 使用覆盖层View,需要处理权限问题,但可以捕获所有触摸事件,包括对话框。 2. 对每个显示的对话框动态添加触摸监听,结合Activity的dispatchTouchEvent来捕获其他事件。 如果用户不想处理权限问题,可能只能选择第二种方法,但需要确保所有对话框都被正确监听。这可能需要在应用架构层面进行统一管理,例如使用基Dialog或者工具来创建所有对话框,并在显示时自动添加监听。 总结步骤: 对于覆盖层方法- 请求SYSTEM_ALERT_WINDOW权限。 - 添加覆盖层View,设置触摸监听。 对于动态对话框监听方法- 在创建每个对话框时,添加OnShowListener,并在其中为对话框的DecorView设置触摸监听。 - 同时,在Activity中重写dispatchTouchEvent以捕获非对话框区域的事件。 这样,两种事件源都能被捕获。 示例代码可能如下: 覆盖层方法(需要权限): ```kotlin // 检查权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) { val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName")) startActivityForResult(intent, REQUEST_CODE) } else { setupOverlay() } private fun setupOverlay() { val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager val params = WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY else WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT ) val overlayView = View(this) overlayView.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { // 处理点击事件 Log.d("Overlay", "Screen clicked") } } false } windowManager.addView(overlayView, params) } ``` 动态对话框监听方法: ```kotlin // 创建对话框时 val dialog = AlertDialog.Builder(this) .setTitle("Dialog") .setMessage("Message") .create() dialog.setOnShowListener { val decorView = dialog.window?.decorView decorView?.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { // 处理对话框区域的点击 Log.d("Dialog", "Dialog clicked") } } false } } dialog.show() // 在Activity中处理其他区域的点击 override fun dispatchTouchEvent(ev: MotionEvent): Boolean { when (ev.action) { MotionEvent.ACTION_DOWN -> { Log.d("Activity", "Activity clicked") } } return super.dispatchTouchEvent(ev) } ``` 结合这两种方法,可以监听Activity和对话框的点击事件。不过,这需要确保所有对话框都设置了监听器,可能比较繁琐。 另外,用户可能需要一个更自动化的方法,例如通过观察所有窗口的添加,或者使用Application级的触摸监控。但Android系统本身没有提供这样的API,可能需要借助反射或其他非公开方法,这可能带来兼容性问题。 综上,最佳的解决方案可能是使用覆盖层,尽管需要处理权限,但能全面捕获所有触摸事件。而另一种方法是结合对话框的监听和Activity的事件处理,但需要额外管理。 最后,根据用户的问题,他们可能希望一个能够监听包括对话框在内的全屏点击的解决方案,所以覆盖层的方法可能更合适,尽管需要处理权限。</think>在 Android 中监听全屏点击事件(包括对话框)可通过以下步骤实现: --- ### 方法 1: 使用覆盖层视图(需权限) 通过 `WindowManager` 添加覆盖层视图,监听全局触摸事件。 **步骤:** 1. **添加权限**: 在 `AndroidManifest.xml` 中声明权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 2. **请求权限**: 在代码中动态请求权限: ```kotlin if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) { val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName")) startActivityForResult(intent, REQUEST_CODE) } else { setupOverlay() } ``` 3. **创建覆盖层视图**: ```kotlin private fun setupOverlay() { val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager val params = WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY else WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT ) val overlayView = View(this).apply { setOnTouchListener { _, event -> if (event.action == MotionEvent.ACTION_DOWN) { Log.d("Overlay", "全局点击事件捕获") } false // 允许事件继续传递 } } windowManager.addView(overlayView, params) } ``` --- ### 方法 2: 动态监听对话框点击 为每个对话框的根视图手动添加触摸监听: ```kotlin val dialog = AlertDialog.Builder(this).setTitle("示例").create() dialog.setOnShowListener { dialog.window?.decorView?.setOnTouchListener { _, event -> if (event.action == MotionEvent.ACTION_DOWN) { Log.d("Dialog", "对话框点击事件捕获") } false } } dialog.show() ``` --- ### 方法 3: 结合 Activity 事件分发 重写 `Activity` 的 `dispatchTouchEvent` 方法监听非对话框区域: ```kotlin override fun dispatchTouchEvent(ev: MotionEvent): Boolean { if (ev.action == MotionEvent.ACTION_DOWN) { Log.d("Activity", "Activity 区域点击") } return super.dispatchTouchEvent(ev) } ``` --- ### 注意事项 1. **覆盖层权限**:`TYPE_APPLICATION_OVERLAY` 需要用户手动授权,可能影响用户体验[^1]。 2. **性能影响**:全局覆盖层可能增加事件处理延迟。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值