最近遇到这么个问题:
在一个移动设备中安装了多个应用程序,其中自己开发的应用需要实现开机自启动这么个功能;
为了实现自己应用能够实现自动启动,最初的思路是监控设备的开机完成这类的广播信号;
思路一(开机自启动):
注册一个静态广播去监听开机启动完毕的广播,然后在接听到开机广播完毕后启动|Activity或者Service;
其中广播监听器中内容为:
public class BootCompletedReceiver extends BroadcastReceiver {
private static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_BOOT_COMPLETED)){
Intent intent=new Intent(context,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
}
必须强调下如果没有设置标记 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
如果不添加这句,就会报 android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity,Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
然后在AndroidManifest.xml静态注册该广播:
<receiver android:name=".BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
然后在AndroidManifest.xml申请权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
通过以上的方法,可以实现开启启动APP,但是,这个方法有问题,以上的方法必须要在安装APP后,手动运行一次APP后,APP才能接收到
android.intent.action.BOOT_COMPLETED
广播。
然而以上的解决思路在Android 3.1之后有了变更;
APP接收不到BOOT_COMPLETED广播可能的原因,有以下几种:
-
对应的BOOT_COMPLETED
和action
没有一起添加uses-permission
- 应用安装到了
卡内,安装在sd
卡内的应用是收不到sd
广播的BOOT_COMPLETED
- 系统开启了
模式,这种模式下系统启动并不会发送Fast Boot
广播BOOT_COMPLETED
- 应用程序安装后重来没有启动过,这种情况下应用程序接收不到任何广播,包括
、BOOT_COMPLETED
、ACTION_PACKAGE_ADDED
等等。CONNECTIVITY_ACTION
Android3.1之后,系统为了加强了安全性控制,应用程序安装后或是(设置)应用管理中被强制关闭后处于stopped状态,在这种状态下接收不到任何广播,除非广播带有
FLAG_INCLUDE_STOPPED_PACKAGES
标志,而默认所有系统广播都是
FLAG_EXCLUDE_STOPPED_PACKAGES
的,所以就没法通过系统广播自启动了。
所以Android3.1之后:
- 应用程序无法在安装后自己启动
- 没有ui的程序必须通过其他应用激活才能启动,如它的Activity、Service、Content Provider被其他应用调用。
不过,存在一种例外,就是应用程序被
adb push you.apk /system/app/
下是会自动启动的,不处于
stopped
状态。解决方式就是将APK推送到
/system/app
目录下,或者打包系统时,将APK放置到
/system/app
中打包
结论是: 我没法将自己的应用安装到系统路径下,无root权限,即无法通过监控开机完成这个广播信号实现自启动了;那么采用思路二;
思路二(其他应用通知启动):
通过其他应用(命名为应用A)发送特定广播信号,我只需监控应用A发送的广播信号即可实现自启动了;
实现:A应用中的Activity发送广播,关键代码如下:
String broadcastIntent = "com.example.BootUp";//自己自定义
Intent intent = new Intent(broadcastIntent);
this.sendBroadcast(intent);
B应用中需要一个BroadcastReceiver来接收广播,取名MyReceiver继承BroadcastReceiver重写onReceive方法启动一个activity,关键代码如下:
if(intent.getAction().equals("com.example.BootUp")){
Intent intent = new Intent(context,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
在AndroidManifest.xml中要对MyReceiver进行注册,代码如下:
<receiver android:name="MyReceiver">
<intent-filter>
<action android:name="com.example.BootUp"/>
</intent-filter>
</receiver>
这样就完成了通过应用A发送的广播启动另一个应用B中的Activity了(上面代码中Activity默认命名为MainActivity)。
注意问题:Context中有一 个startActivity方法,Activity继承自Context,重载了startActivity方法。如果使用 Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的话,就需要开启一个新 的task,解决办法是,加一个flag,也就是这句 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);的作用。
开机自启动问题参考:https://segmentfault.com/q/1010000015837899
广播receiver中启动Activity参考:https://blog.csdn.net/u014005316/article/details/53671673
https://www.cnblogs.com/zhujiabin/p/4262049.html