1.前言
在12.0的系统rom定制化开发中,由于有些第三方app,需要在接收到开机广播后,启动app,但是在10.0以后第三方app就接收不到开机广播了
只有系统app才可以接收到开机广播了,所以在app内通过接收开机广播自启动就没法实现了 这就需要在系统中添加 监听Q 开机完成广播的功能,然后在接收到开机广播后启动第三方app就可以了
2.系统开机自启动第三方app的核心类
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
3.系统开机自启动第三方app的核心功能分析和实现
3.1 app中常用的接收开机广播的方法
<receiver
android:name=".receiver.StartSelfReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
在app中使用的范例
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.pne.kotlin.ReplaceIconActivity;
public class StartSelfReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e("Receiver","action:"+action);
//Android设备开机时会发送一条开机广播:"android.intent.action.BOOT_COMPLETED"
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Intent selfIntent = new Intent(context, ReplaceIconActivity.class);
selfIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(selfIntent);
}
}
}
这种方式会收不到开机广播的,所以对于启动app也是做不到的,接下来就只能在framework中某个功能模块里面接收到开机广播后,启动某个app了
3.2 PhoneWindowManager.java中启动第三方app的功能实现
/** {@inheritDoc} */
@Override
public void systemReady() {
// In normal flow, systemReady is called before other system services are ready.
// So it is better not to bind keyguard here.
mKeyguardDelegate.onSystemReady();
mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
if (mVrManagerInternal != null) {
mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
}
readCameraLensCoverState();
updateUiMode();
mDefaultDisplayRotation.updateOrientationListener();
synchronized (mLock) {
mSystemReady = true;
mHandler.post(new Runnable() {
@Override
public void run() {
updateSettings();
}
});
// If this happens, for whatever reason, systemReady came later than systemBooted.
// And keyguard should be already bound from systemBooted
if (mSystemBooted) {
mKeyguardDelegate.onBootCompleted();
}
}
//add code start
IntentFilter intentFilter = new IntentFilter("android.intent.action.BOOT_COMPLETED");
mContext.registerReceiver(mWallpaperChangedReceiver, intentFilter);
//add code end
mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
mGestureLauncherService = LocalServices.getService(GestureLauncherService.class);
}
/** {@inheritDoc} */
@Override
public void systemBooted() {
bindKeyguard();
synchronized (mLock) {
mSystemBooted = true;
if (mSystemReady) {
mKeyguardDelegate.onBootCompleted();
}
}
mSideFpsEventHandler.onFingerprintSensorReady();
startedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
finishedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
int defaultDisplayState = mDisplayManager.getDisplay(DEFAULT_DISPLAY).getState();
boolean defaultDisplayOn = defaultDisplayState == Display.STATE_ON;
boolean defaultScreenTurningOn = mDefaultDisplayPolicy.getScreenOnListener() != null;
if (defaultDisplayOn || defaultScreenTurningOn) {
// Now that system is booted, wait for keyguard and windows to be drawn before
// updating the orientation listener, stopping the boot animation and enabling screen.
screenTurningOn(DEFAULT_DISPLAY, mDefaultDisplayPolicy.getScreenOnListener());
screenTurnedOn(DEFAULT_DISPLAY);
} else {
// We're not turning the screen on, so don't wait for keyguard to be drawn
// to dismiss the boot animation and finish booting
mBootAnimationDismissable = true;
enableScreen(null, false /* report */);
}
}
// add core start
BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("android.intent.action.BOOT_COMPLETED")) {
Slog.d("WindowManager", "android.intent.action.BOOT_COMPLETED");
Intent selfIntent = new Intent(context, ReplaceIconActivity.class);
selfIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(selfIntent);
}
}
};
//add core end
在上述的PhoneWindowManager.java中相关源码可以看出,在系统相关服务启动完毕后,在调用 systemReady()执行PhoneWindowManager.java的相关功能中,可以添加相关的开机启动完成广播的监听,然后在广播中,收到开机完成广播以后,启动第三方app就实现了功能的需求