目录

Android开发中,有哪些坑需要注意

Android开发中,需要注意的坑有:1、OPPO手机无法后台弹窗、弹页面;2、OPPO手机无法进入debug调试模式;3、系统更换语言、方向、分屏等导致app崩溃等。OPPO手机无法后台弹窗、弹页面是指调用语句无法在OPPO手机调出后台弹窗。

1、OPPO手机无法后台弹窗、弹页面

通常后台弹窗的做法为:

Intent it = new Intent(context,activity.class);
it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(it);

这是很正常也很官方的调用方法,Android原生系统没有任何问题,但在OPPO手机(系统)上表现为后台无法弹出页面。

解决方法:提示用户去开启自启动权限,或者在交互中添加通知栏的弹出通知(建议通过极光弹本地通知栏),用户可以点击通知栏跳转至相应的页面。

2、OPPO手机无法进入debug调试模式

通过数据线连接OPPO手机(系统),打开对应的开发者选项和USB调试,在IDE中调试手机时无法进入debug模式。有时表现为进入debug模式一小段时间后,系统强制弹出app安装成功界面打断debug模式。

解决方法:换手机开发。

3、系统更换语言、方向、分屏等导致app崩溃

用户在更换语言、方向、分屏等操作时,系统有可能会强制更新app的UI界面,从而引发空指针异常导致app崩溃。

解决方法:在AndroidManifast的Activity中声明在这些操作时不需要更新UI。

<activity android:name="xxxx" android:configChanges="orientation|keyboardHidden|smallestScreenSize|screenLayout|screenSize|locale|layoutDirection" />

4、锁屏状态弹页面“闪退”

要想实现在锁屏状态下弹界面并且点亮屏幕等操作,需要在Activity中设置属性:

WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED

点亮屏幕后,系统认为还在休眠状态,故将Activity Finish掉了。

解决方法:修改为以下代码:

onCreate()中:   

getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

onS较好()中:

//When show alarmalert on lockscreen, AlarmAlert will go to onS较好(), so it flush even though    
    //set FLAG_SHOW_WHEN_LOCKED, so on lockscreen return directly. 20130402, gwb.
    KeyguardManager keyguardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
    if (keyguardManager.isKeyguardLocked() && !mIsS较好pedByAMSOnce) {
        mIsS较好pedByAMSOnce = true;
        return;
    }

5、荣耀部分手机(或部分系统版本)容易OOM

OOM,即OutOfMemoryError,原因是荣耀部分机型上的线程数限制非常严苛。

解决方法:加入线程池控制app所有的线程执行,或者减少线程数。

6、后台保活复活对应的service抛出IllegalStateException

由于需求需要,app做了后台保活措施,但在Android O(或Android One)上表现为一直抛出IllegalStateException,导致app一直崩在后台(虽然用户不知道)。原因为Android8.0之后不再允许app在后台启动service。

解决方法:把工程中所有的service变成jobservice,并做好系统版本判断,针对不同的android版本做不同的保活措施。

7、OPPO手机(系统)有时app退至后台即被杀死

OPPO手机(系统)有后台冻结机制,有时对于小厂app不会留存任何后台,退至后台即被杀死,从而导致无法再为用户提供服务。

解决方法:手机中加入常见问题解决方法,指引用户给app留后台。

8、加入重力感应后,可能导致部分手机频繁ANR

在部分手机上,重力感应监听会导致手机卡顿。

解决方法:尽量让app的方向跟随系统,用户没开重力感应开关时不去监听手机重力感应。

9、JobService的onStartJob()方法不会立即执行

android5.0之后Google官方推荐将所有的Service替换为JobService的方式去实现相应的需求,android8.0之后更是不再允许app在后台startService。所以,为了更好的适配,大部分开发者工程中都会加入JobService。但是执行JobService之后,onStartJob并不会立即执行,可能会等到10多分钟之后才执行。

代码如下:

JobInfo.Builder builder - new JobInfo.Builder(ID,new ComponentName(context,xxxJobService.class));
builder.setPeriodic(3000);//每3s执行一次
builder.setPersisted(true);//设备重启时执行
builder.setRequiresCharging(true);//插入充电器时执行
JobInfo info = builder.build();
mJobScheduler.schedule(info);//以系统调度的方式执行

运行之后可以发现,JobService中的onStartJob方法不会立即执行,注意Logcat中的打印,有这么一句话:

W/JobInfo:Specified interval for 1 is + 2s0ms.Clamped to +15m0s0ms

也就是onStartJob至少会在15分钟之后才会执行。

解决方法:换种调用方法,即将builder.setPeriodic(3000)换成builder.setOverrideDeadline(2000),或者换成builder.setMinimumLatency()。 注意,两个方法不能同时使用。

10、在Android library中不能使用switch-case语句访问资源ID

当我们在Android依赖库中使用switch-case语句访问资源ID时会报如下图所示的错误:

报的错误是case分支后面跟的参数必须是常数,换句话说出现这个问题的原因是Android library中生成的R.java中的资源ID不是常数。

解决方法:既然是由于library的R.java中的资源ID不是常量引起的,我们可以在library中通过if-else-if条件语句来引用资源ID,这样就避免了这个错误。

11、不能在Activity没有完全显示时显示PopupWindow

在某些情况下,我们需要一进入Activity就显示PopupWindow,比如常见的选择界面。但由于PopupWindow是依附于Activity的,如果Activity没有创建完成,Activity还没完全显示出来就显示PopupWindow的话,会出现异常现象。

解决方法:弹出窗口与描点控件有着紧密的联系,在构造并展示弹出窗口前,需要保证锚点控件所在的控件树已经与窗口管理服务建立连接,因为在弹出窗口的展示过程中,需要通过该窗口对象来获取相关信息。在界面组件的构造过程中,窗口连接的建立是个异步过程,也就是说,当Activity.onCreate()等函数被调用时,界面与窗口管理服务的双向通信连接尚未建立,如果在此时构造弹出窗口则会抛出异常。因此,如果期望在界面组件展现之处便构造弹出窗口,可以将弹出窗口对象构造也转换成一个异步过程:

// 在界面组件onCreate函数中调用  
final View anchor = findViewById(R.id.anchor);  
    anchor.post(new Runnable(){  
    @Override  
    public void run(){  
        // 构造和展现弹出窗口  
        PopupWindow window = createWindow();  
        window.showAsDropDown(anchor);  
    }  
});  

在与窗口管理服务未建立连接之前,界面组件将通过View.post函数发送过来的消息放入一个静态队列当中,在通信连接建立完成后,再从该队列中读取消息并一一执行。因此,通过这样的实现模型可以保证弹出窗口展现时窗口通信连接已经构建成功。

所以对于上面的问题,最简单的处理方法是,异步显示PopupWindow:

public void show( ){  
    mView.post( new Runnable( ) {  
        @Override  
        public void run() {  
            if( null != mPopupWindow ){  
                mPopupWindow.showAtLocation(mView, Gravity.CENTER, 0, 0);  
            }  
        }  
    });  
}  

12、在多进程之间不要用SharedPreferences共享数据

在使用SharedPreference 时,有一些模式:MODE_PRIVATE 私有模式,这是最常见的模式,一般情况下都使用该模式。 MODE_WORLD_READABLE,MODE_WORLD_WRITEABLE ,文件开放读写权限,不安全,已经被废弃了,google建议使用FileProvider共享文件。MODE_MULTI_PROCESS,跨进程模式,如果项目有多个进程使用同一个Preference,需要使用该模式,但是也已经废弃了。

解决方法:Android不保证该模式总是能正确的工作,建议使用ContentProvider替代。

延伸阅读1:Android概述

Android 是一个开源的,基于 Linux 的移动设备操作系统,如智能手机和平板电脑。Android 是由谷歌及其他公司带领的开放手机联盟开发的。Android 提供了一个统一的应用程序开发方法,这意味着开发人员只需要为 Android 进行开发,这样他们的应用程序就能够运行在不同搭载 Android 的移动设备上。谷歌在2007年发布了名列前茅个测试版本的 Android 软件开发工具包(SDK),名列前茅个商业版本的 Android 1.0,则发布于2008年9月。