Android App 开机自启动

Android App 开机自启动,第1张

<article class="_2rhmJa">

Android 设备开机自启动的可以用广播实现没弊枝,因为 Android 设备开机时会发送一条开机广播 "android.intent.action.BOOT_COMPLETED"。接收后实现启动就完成了。

接下来是准备工作

如果按照上面的全部步骤后 *** 作后,重启没有自动启动程序,怎么办呢?是怎么回事呢?

*那么首先请检查一下你的手机是不是安装了360等安全助手之类的枯敏软件,如果有,请在软件的自启动软件管理中将app设置为允许

*我的手机没有安装这些软件,但是手机中自带了安全助手,有的手机系统设置里面自带了自启卜亩动软件管理的功能 ,所以在这里将我们的app设置为允许开机启动),重启手机,测试是否成功。

然而并没有成功

接收不到BOOT_COMPLETED广播可能的原因

(1)、BOOT_COMPLETED对应的action和uses-permission没有一起添加

(2)、应用安装到了sd卡内,安装在sd卡内的应用是收不到BOOT_COMPLETED广播的

(3)、系统开启了Fast Boot模式,这种模式下系统启动并不会发送BOOT_COMPLETED广播

(4)、应用程序安装后重来没有启动过,这种情况下应用程序接收不到任何广播,包括BOOT_COMPLETED、ACTION_PACKAGE_ADDED、CONNECTIVITY_ACTION等等。

Android3.1之后,系统为了加强了安全性控制,应用程序安装后或是(设置)应用管理中被强制关闭后处于stopped状态,在这种状态下接收不到任何广播,除非广播带有FLAG_INCLUDE_STOPPED_PACKAGES标志,而默认所有系统广播都是FLAG_EXCLUDE_STOPPED_PACKAGES的,所以就没法通过系统广播自启动了。所以Android3.1之后

(1)、应用程序无法在安装后自己启动

(2)、没有ui的程序必须通过其他应用激活才能启动,如它的Activity、Service、Content Provider被其他应用调用。

存在一种例外,就是应用程序被adb push you.apk /system/app/下是会自动启动的,不处于stopped状态。

并不太懂 我的APP启动后 已经收到广播

第一种方式 我再模拟器上 测试 可以 android 9.0版本

桌面设置也会把你的app当成一个桌面主题,还有一个选项是系统桌面,你需要设置成自己的app

如果找不到桌面设置选项,可以从手机设置–应用程序-查看所有应用程序(包括系统的应用程序),找到桌面程序之类的字眼的应用,清楚其默认设置。

以下广播简称Broadcast

  是Android四大组件之一,在四大组件的另外两个组件 和 拥有发送和接收广播的能力。Android 是在 进程间通信机制的基础上实现的,内部基于消息发布和订阅的事件驱动模型,广播发送者负责发送消息,广播接收者需要先订阅消息,然后才能收到消息。 进程间通信与 的区别在于:

  棚宏源有三种类型

   存在一个注册中心,也可以说是一个调度中心,即 。广播接收者将自己注册到 中,并指定要接收的广播类型;广播发送者发送广播时,发送的广播首先会发送到 , 根据广播的类型找到对应的 ,找到后边将广播发送给其处理。

   这里以普通广播为例子, 接收者有两种注册方式,一种是 ,一种是 :

(广播的发送分为 两种,这里针对有序的广播) 中的android:priority=""和 中的IntentFilter.setPriority(int)可以用来设置广播接收者的优先级,默认都是0 , 范围是[-1000, 1000],值越大优先级越高,优先级越高越早收到。

   在相同优先级接收同个类型广播时, 的广播接收器比 的广播接收者更快的接收到对应的广播,这个之后会进行分析。

   注:以下源码基于rk3399_industry Android7.1.2

   的流程可分为 , 和 三个部分,这里依次分析下

   在链态Android系统的 机制中,前面提到, 作为一个注册和调度中心负责注册和转发 。所以 的注册过程就是把它注册到 的过程。

   这里我们分析 广播的过程, 和 有一个共同的父类 ,所以它们对应的注册过程其实是调用 ,接下来我们按照流程逐步分析调用流程的源码。

frameworks/base/core/java/android/content/ContextWrapper.java

   在之前的 Android应用程序启动入口ActivityThread.main流程分析 分析过,在我们启动 Activity 时会创建一个 对象,然后通过 传给我们启动的 ,其内部就会将该对象赋值给 ; 的 方法也是类似的赋值流程,这里放个简易的源码应该更好理解

   可以看到最后都会将生成的 对象赋值给对应的

对象。接下来继续分析 , 即 函数。

/frameworks/base/core/java/android/app/ContextImpl.java

   这里我们首先看下如何将广播接收者 封装成一个 接口的 本地对象

/frameworks/base/core/java/android/app/LoadedApk.java

   每一个注册过广播接收者的 或 组件在<font color='Crimson'>LoadedApk </font>类中都有个绝告对应的 对象,该对象负责将 与 组件关联起来。这些对象,以关联的 作为关键字保存在一个 中。之后对应的 又以 的 作为关键字保存在 的成员变量 对象中。最后通过 对应的 方法获得其 接口的 本地对象。之后再回到 注册方法内,将 对象发给 进行注册。

/frameworks/base/core/java/android/app/ActivityManagerNative.java

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

   在的 或 注册一个 时,并不是将其注册到<font color='OrangeRed'>AMS</font>中,而是将与它关联的<font color='OrangeRed'>InnerReceiver</font>对象注册到<font color='OrangeRed'>AMS</font>中,当<font color='OrangeRed'>AMS</font>接收到广播时,会根据 在内部找到对应的<font color='OrangeRed'>InnerReceiver</font>对象,然后在通过这个对象将这个广播发送给对应的 处理。

   注册过程这边画了一个简单的流程图:

   <font color='OrangeRed'>Broadcast</font>的发送过程可简单描述为以下几个过程:

frameworks/base/core/java/android/content/ContextWrapper.java

/frameworks/base/core/java/android/app/ContextImpl.java

/frameworks/base/core/java/android/app/ActivityManagerNative.java

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

现在有应用A和应用B,我需要在A应用中槐枝启动B应用中的某个Activity

实现:A应用中的Activity发送广播,关键代码如下:

String broadcastIntent = "com.example.android.notepad.NotesList"//自己裂困自定义

Intent intent = new Intent(broadcastIntent)

this.sendBroadcast(intent)

B应用中需要一个BroadcastReceiver来接收广播,取名TestReceiver继承BroadcastReceiver重写onReceive方法启动一个activity,关键代码如下:

if(intent.getAction().equals("com.example.android.notepad.NotesList")){

Intent noteList = new Intent(context,NotesList.class)

noteList.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

context.startActivity(noteList)

}

到这代码就完成了,当然在AndroidManifest.xml中要对TestReceiver进行注册,代码如下:

<receiver android:name="TestReceiver">

<intent-filter>

<action android:name="com.example.android.notepad.NotesList"/>

</intent-filter>

</receiver>

这样就完成了通过广播启动另一个应用Activity。

注意问题:Context中有一个startActivity方法,Activity继承自Context,重载了startActivity方法肆明念。如果使用 Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的话,就需要开启一个新的task,解决办法是,加一个flag,也就是这句noteList.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?

分类: Android


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12293323.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-22
下一篇2023-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存