Restart when lock screen Android phone how quick start Launcher

Launcher Overview

The last step is to start Android system starts a Home application, this application is used to display the application system has been installed, this application is called Home Launcher. Launcher application in the startup process will return information PackageManagerService application system has been installed, and information is encapsulated into a list of shortcut icons displayed on the system screen, so that users can start the appropriate application by clicking the icon shortcut .

 

Launcher startup process

We can simply be summarized as, a Launcher application, the application in the main Activity AndroidManifest.xml file which is configured to Action Intent.ACTION_MAIN, Category of Intent.CATEGORY_HOME, as shown below.

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.launcher3">
    <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/>
   
    ....
    <application
        ...
        android:largeHeap="@bool/config_largeHeap"
        android:restoreAnyVersion="true"
        android:supportsRtl="true" >

        -->
        <activity
            android:name="com.android.launcher3.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="unspecified"
            android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
            android:resizeableActivity="true"
            android:resumeWhilePausing="true"
            android:taskAffinity=""
            android:enabled="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
                <category android:name="android.intent.category.LAUNCHER_APP" />
            </intent-filter>
        </activity>
....
    </application>
</manifest>

ActivityManagerService application is started by a system service, AMS starts after phone restart Launcher application of this process and start the ordinary procedure is not much different, just need to find the AMS Launcher application, are as follows Launcher start of Intent method because Launcher application is configured Therefore, the AMS may Category filtered by this condition is all Intent.CATEGORY_HOME Launcher application, if there are multiple Launcher box will pop up to the user to select.

Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

problem analysis:

In accordance with normal procedures after phone restart Launcher should soon be launched, but when the phone has power on but the user has to unlock and lock screen time, Android N run in a safe mode, that is, Dierect Boot mode, the Normal mode applications can not start out a lot of authority banned, so AMS is not the first time to start the Launcher application, but by the Setting application launch, Setting program is broadcast in listening to unlock Launcher application to determine whether to activate if the start is Close seting launcher interface display interface, the interface from entering Setting Launcher to start the process and then Launcher screen display takes about three seconds, which led to the first time after unlocking can not see the Launcher screen to start.

Here is Setting Application Launcher's startup process

In the course of the analysis found 7.0 before starting Launcher will first start a FallbackHome, then will start the Launcher, through the survey found FallbackHome belong to one of the activity Settings, Settings of android: directBootAware is true, and FallbackHome configured in the category of Home Properties while the Launcher android: directBootAware is false, all FallbackHome can start only in the direct boot mode.
 

 <!-- Triggered when user-selected home app isn't encryption aware -->
        <activity
                android:name=".FallbackHome"
                android:excludeFromRecents="true"
                android:label=""
                android:screenOrientation="behind"
                android:theme="@style/FallbackHome">
            <intent-filter android:priority="-1000">
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.HOME"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

FallbackHome Launcher to start the process

FallbackHome code is very simple is a transparent layout tips Laucher is starting up, listening to unlock broadcast Intent.ACTION_USER_UNLOCKED event, received after unlocking event with Handler loop to determine whether Launcher to start, if not start then continue once every 500 milliseconds judgment until the start Launcher it closes the window display Launcher interface

private void maybeFinish() {
        if (getSystemService(UserManager.class).isUserUnlocked()) {
            final Intent homeIntent = new Intent(Intent.ACTION_MAIN)
                    .addCategory(Intent.CATEGORY_HOME);
            final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, 0);
            if (Objects.equals(getPackageName(), homeInfo.activityInfo.packageName)) {
                if (UserManager.isSplitSystemUser()
                        && UserHandle.myUserId() == UserHandle.USER_SYSTEM) {
                    // This avoids the situation where the system user has no home activity after
                    // SUW and this activity continues to throw out warnings. See b/28870689.
                    return;
                }
                Log.d(TAG, "User unlocked but no home; let's hope someone enables one soon?");
                mHandler.sendEmptyMessageDelayed(0, 500);
            } else {
                Log.d(TAG, "User unlocked and real home found; let's go!");
                getSystemService(PowerManager.class).userActivity(
                        SystemClock.uptimeMillis(), false);
                finish();
            }
        }
    }

The complete code is as follows 

public class FallbackHome extends Activity {
    private static final String TAG = "FallbackHome";
    private static final int PROGRESS_TIMEOUT = 2000;

    private boolean mProvisioned;

    private final Runnable mProgressTimeoutRunnable = () -> {
        View v = getLayoutInflater().inflate(
                R.layout.fallback_home_finishing_boot, null /* root */);
        setContentView(v);
        v.setAlpha(0f);
        v.animate()
                .alpha(1f)
                .setDuration(500)
                .setInterpolator(AnimationUtils.loadInterpolator(
                        this, android.R.interpolator.fast_out_slow_in))
                .start();
        getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set ourselves totally black before the device is provisioned so that
        // we don't flash the wallpaper before SUW
        mProvisioned = Settings.Global.getInt(getContentResolver(),
                Settings.Global.DEVICE_PROVISIONED, 0) != 0;
        if (!mProvisioned) {
            setTheme(R.style.FallbackHome_SetupWizard);
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        } else {
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
        }

        registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
        maybeFinish();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mProvisioned) {
            mHandler.postDelayed(mProgressTimeoutRunnable, PROGRESS_TIMEOUT);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mHandler.removeCallbacks(mProgressTimeoutRunnable);
    }

    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            maybeFinish();
        }
    };

    private void maybeFinish() {
        if (getSystemService(UserManager.class).isUserUnlocked()) {
            final Intent homeIntent = new Intent(Intent.ACTION_MAIN)
                    .addCategory(Intent.CATEGORY_HOME);
            final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, 0);
            if (Objects.equals(getPackageName(), homeInfo.activityInfo.packageName)) {
                if (UserManager.isSplitSystemUser()
                        && UserHandle.myUserId() == UserHandle.USER_SYSTEM) {
                    // This avoids the situation where the system user has no home activity after
                    // SUW and this activity continues to throw out warnings. See b/28870689.
                    return;
                }
                Log.d(TAG, "User unlocked but no home; let's hope someone enables one soon?");
                mHandler.sendEmptyMessageDelayed(0, 500);
            } else {
                Log.d(TAG, "User unlocked and real home found; let's go!");
                getSystemService(PowerManager.class).userActivity(
                        SystemClock.uptimeMillis(), false);
                finish();
            }
        }
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            maybeFinish();
        }
    };
}

Quick Start Program Launcher:

Based on the analysis above, we know that non-directBootAware Launcher application, PMS in the lead this time limit can not start Launcher, Launcher can not make it the first time to start, in that case we just let Launcher also supports directBootAware on it, this process encountered a problem: the Launcher application will result in marked directBootAware boot Launcher crash. Because in Launcher widget is still non-directBootAware at this time still can not be started unless the widget-related APP are marked directBootAware, this widget we can make a deal to delay loading.

The following is a specific embodiment of the process:

1. First, we need to support Launcher support directBootAware, can be configured as follows

android:defaultToDeviceProtectedStorage="true"

android:directBootAware="true"

<application
        android:backupAgent=".LauncherBackupAgent"
        android:fullBackupContent="@xml/backupscheme"
        android:fullBackupOnly="true"
        android:defaultToDeviceProtectedStorage="true"
        android:directBootAware="true"
        android:hardwareAccelerated="true"
        android:icon="@drawable/ic_launcher_home"
        android:label="@string/derived_app_name"
        android:theme="@style/AppTheme"
        android:largeHeap="@bool/config_largeHeap"
        android:networkSecurityConfig="@xml/network_security_config"
        android:restoreAnyVersion="true"
        android:supportsRtl="true">

2. delay loading widget, the following method is to load the widget, we can listen to broadcast events to unlock, unlock after a delay of 500 milliseconds reload widget

mAppWidgetHost = new LauncherAppWidgetHost(this); mAppWidgetHost.startListening();

to sum up:

Because many manufacturers do Launcher customized so in accordance with the above program may experience startup problems, but these problems can be handled one by one, in fact, in order to avoid the above problem, we can j can be loaded with a simple desktop interface, etc. unlock loaded once again.

Published 92 original articles · won praise 27 · views 90000 +

Guess you like

Origin blog.csdn.net/zhuxingchong/article/details/100915030