Android 自定义启动器 startActivity() 阻止 BOOT_COMPLETED 意图

Posted

技术标签:

【中文标题】Android 自定义启动器 startActivity() 阻止 BOOT_COMPLETED 意图【英文标题】:Android Custom Launcher startActivity() blocks BOOT_COMPLETED intent 【发布时间】:2014-11-11 07:35:21 【问题描述】:

我目前正在开发自定义 ROM(基于 CyanogenMod 11.0),旨在实现自定义“Kiosk 模式”。为此,我在一个应用程序中包含三个组件(具有系统权限): 服务,它处理对状态/导航栏的修改并禁用电源键。接收者,只有在收到BOOT_COMPLETED 信号后才启动服务。 HomeIntentWrapper 用作启动器,仅启动一个自定义活动。

我目前面临的问题是HomeIntentWrapper 中的startActivity(...) 命令以某种方式阻止系统进一步启动,并且永远不会发送BOOT_COMPLETED 意图。

我使用adb shell dumpsys activity 命令验证了这一点,它告诉我:

mStartedUsers:
  User #0: mState=BOOTING

它也不显示曾经发送的BOOT_COMPLETED 广播。

现在,如果用户按下 Home-Button,则发送 BOOT_COMPLETED 意图,并且 mState 切换到 RUNNING

如果我没有在HomeIntentWrapper 中启动活动,则会发送意图。我在这里做错了什么?

androidManifest.xml:

<manifest coreApp="true">
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />    

    <application android:allowBackup="true"
                 android:persistent="true" >

        <service android:name="Service" 
                 android:process=":service" >
            </intent-filter>
        </service>

        <receiver android:name="Receiver" 
                  android:process=":receiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <activity android:name="HomeIntentWrapper"
                  android:process=":launcher" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

接收者:

public class Receiver extends BroadcastReceiver 
    @Override
    public void onReceive(Context context, Intent intent) 
        context.startService(new Intent(context, Service.class));
    
 

HomeIntentWrapper:

public class HomeIntentWrapper extends Activity 
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        startApp();
    

    @Override
    protected void onResume() 
        super.onResume();
        startApp();
    

    private void startApp() 
        SharedPreferences sharedPrefs = getSharedPreferences(getString(R.string.settings_file), Context.MODE_MULTI_PROCESS);
        String customAppIntentString = sharedPrefs.getString(getString(R.string.settings_custom_intent), "");

        if(customAppIntentString.equals("") == false) 
            try 
                Intent intent = Intent.getIntent(customAppIntentString);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
             catch(java.net.URISyntaxException e) 
                // Intentionally
            
        
    

【问题讨论】:

【参考方案1】:

根本原因:finishBooting() 未被调用,因为 Home Activity 不在堆栈顶部。

http://androidxref.com/4.4.4_r1/xref/frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java

线路:1811 线路:1883-1886 行:1934-1940

解决方案:

在收到 Boot_Completed 之前不要调用 start Activity。

【讨论】:

也许你可以帮助我。我有这种情况,即不调用 ActivityManagerService#finishBooting()(不发送 BOOT_COMPLETED),因为有时会在 ActivityStackSupervisor#activityIdleInternalLocked() 之后调用 ActivityManagerService#systemReady()。现在,systemReady() 设置 mBooting=true,并且必须在 activityIdleInternalLocked() 检查它之前将其设置为 true 才能调用 finishBooting()。似乎存在竞争条件,因为有时它有效,有时则无效。你知道会发生什么吗?

以上是关于Android 自定义启动器 startActivity() 阻止 BOOT_COMPLETED 意图的主要内容,如果未能解决你的问题,请参考以下文章

Android 自定义启动器 startActivity() 阻止 BOOT_COMPLETED 意图

从 android 浏览器启动自定义 android 应用程序

如何停止以自定义意图启动的 Android 服务

使用自定义 Google Now 命令启动 Android 应用

Android 存储访问框架 - 自定义文件类型的启动选择器

Android 12之启动画面Splash Screens -- 适配