Android пин-активность при загрузке

У меня есть приложение, которое регистрирует себя как средство запуска по умолчанию и автоматически прикрепляет себя при запуске.

Все это прекрасно работает при установке приложения. Он прикрепляется сам, и видна только кнопка возврата.

Проблема в том, что когда устройство загружается впервые, оно не прикрепляется должным образом. Я вижу серию тостов "Экран закреплен" и "Экран закреплен" несколько раз. Кнопки "Домой" и "Недавние задачи" также видны.

-

Запустите "Действия активности adb shell dumpsys" - последние строки указывают, что он не закреплен:

mLockTaskModeState=NONE mLockTaskPackages (userId:packages)=
0:[com.example.myapp]
mLockTaskModeTasks[]

-

Испытательное устройство Asus ZenPad под управлением Marshmallow/6.0/23

Я полагаюсь на атрибут манифеста MainActivity "lockTaskMode", чтобы закрепить (а не Activity.startLockTask()):

<activity
    android:name=".MainActivity"
    android:configChanges="keyboardHidden|orientation|screenSize"
    android:label="@string/launcher_main"
    android:launchMode="singleTask"
    android:lockTaskMode="if_whitelisted"
    android:screenOrientation="landscape">
    <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.LAUNCHER"/>
    </intent-filter>
</activity>

Любая помощь или указатели будут оценены

3 ответа

У меня была такая же проблема, и я действительно мог найти только одно решение. Я не уверен, почему, но да, что-то в android предотвращает блокировку задач при загрузке, что поражает меня, так как блокировка задач была разработана для создания таких приложений типа "киоска". Единственное решение, которое я смог найти, - это обнаружить случай, когда оно не заблокировано, а затем перезапустить приложение. Это немного "хаки", но что еще ты можешь сделать?

Чтобы обнаружить случай, когда он не заблокирован, я создал переменную состояния и назначил состояния (Locking, Locked, Unlocking, Unlocked). Затем в приемнике администратора устройства в onTaskModeExiting, если состояние не "Разблокировка", я знаю, что оно разблокировано само по себе. Поэтому, если этот случай произошел там, где произошел сбой, я затем перезапускаю приложение, используя этот метод (который планирует приложение в диспетчере аварийных сигналов, а затем убивает приложение):

как программно "перезагрузить" андроид приложение?

Вот пример кода:

DeviceAdminReceiver

@Override
public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
    super.onLockTaskModeEntering(context, intent, pkg);
    Lockdown.LockState = Lockdown.LOCK_STATE_LOCKED;
}

@Override
public void onLockTaskModeExiting(Context context, Intent intent) {
    super.onLockTaskModeExiting(context, intent);

    if (Lockdown.LockState != Lockdown.LOCK_STATE_UNLOCKING) {
        MainActivity.restartActivity(context);
    }
    Lockdown.LockState = Lockdown.LOCK_STATE_UNLOCKED;
}

Основная деятельность

public static void restartActivity(Context context) {
    if (context != null) {
        PackageManager pm = context.getPackageManager();
        if (pm != null) {
            Intent intent = pm.getLaunchIntentForPackage(context.getPackageName());
            if (intent != null) {
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                int pendingIntentId = 223344;
                PendingIntent pendingIntent = PendingIntent.getActivity(context, pendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
                AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
                mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
                System.exit(0);
            }
        }
    }
}

private void lock() {
    Lockdown.LockState = Lockdown.LOCK_STATE_LOCKING;
    startLockTask();
}

private void unlock() {
    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    if (am.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED) {
        Lockdown.LockState = Lockdown.LOCK_STATE_UNLOCKING;
        stopLockTask();
    }
}

По правде говоря, это упрощенная версия того, что я реализовал. Но мы надеемся, что это поможет вам найти решение.

Единственное решение, которое я нашел на данный момент: создать еще одно приложение запуска, без locktask, которое будет запускать основное приложение каждый раз, когда появляется средство запуска. Это не позволяет пользователю подождать еще несколько секунд, прежде чем вызывается приложение LockTasked на приемнике BOOT_COMPLETED. Таким образом, мы можем решить эту проблему только тогда, когда приложение lockTask имеет свойства запуска для некоторого действия в манифесте.

Извините за поздний ответ, но...
Любой, у кого есть эта проблема, может выполнить эту сложную работу в первом (LAUNCHER/HOME) действии (например, MainActivity):

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

    if (mSharedPreferences.getBoolean(KEY_PREF_RECREATED, false)) {
        mSharedPreferences.edit().putBoolean(KEY_PREF_RECREATED, false).apply();

        // start LOCK TASK here
    } else {
        mSharedPreferences.edit().putBoolean(KEY_PREF_RECREATED, true).apply();

        finish(); // close the app
        startActivity(new Intent(this, MainActivity.class)); // reopen the app
        return;
    }

    setContentView(R.layout.activity_main);

    // other codes
}
Другие вопросы по тегам