Режим киоска для android
У меня есть гибридное приложение, написанное на phonegap для планшетов android. Теперь я хочу, чтобы планшет показывал только мое приложение. В основном я хочу, чтобы планшет всегда был в режиме киоска, работающем только с моим приложением. Так что все кнопки отключены. Я искал решения в интернете, и один из них-использовать "surelock", но он не делает все вышеперечисленное. Другой вариант-написать свой собственный ПЗУ, однако я не смог найти хороших учебников по этому вопросу. Кто-нибудь может мне помочь?
6 ответов
Я сделал много исследований, и теперь, наконец, я доволен тем, что я получил.
у вас в основном есть два варианта:
создайте свой собственный ПЗУ, что не является лучшим решением для меня.
настройка планшетов с помощью различных хаков.
поэтому я буду объяснять второй вариант.
сначала вам нужно укоренить свои устройства. Существуют различные методы, но я предпочитаю укоренение программное обеспечение лучше. Для китайских планшетов вы можете использовать VROOT, а для более популярных-Kingo root.
теперь, когда у вас есть устройство коренится, мы можем избавиться от верхней и нижней панели.
private void hideBar(){
    try
    {
        Process proc = Runtime.getRuntime().exec(new String[]{"su","-c","service call activity 42 s16 com.android.systemui"}); 
        proc.waitFor();
    }
    catch(Exception ex)
    {
        Toast.makeText(getApplicationContext(), ex.getMessage(), Toast.LENGTH_LONG).show();
        Log.e("ROOT ERROR", ex.getMessage());
    }
}
Это заставит верхнюю и нижнюю панель исчезнуть. Однако вам, вероятно, понадобится способ снова показать бары. Для этого вы можете использовать:
public void showBars(){
    try 
    {
        String command;
        command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService";
        String[] envp = null;
        Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }, envp);
        proc.waitFor();
    } 
    catch(Exception ex)
    {
        Toast.makeText(context.getApplicationContext(), ex.getMessage(), Toast.LENGTH_LONG).show();
    }
}
Ok Итак, у нас есть это, все, что осталось, это запустить ваше приложение во время загрузки. Для этого вы можете найти много учебники, просто погуглите.
с Android L-release (Lollipop) есть функция, называемая закреплением, которая в значительной степени эквивалентна режиму киоска. Вот ссылка, которая объясняет, как его настроить.
Я считаю, что Apple представила это впервые в iOS. Несмотря на то, что OP не спросил, я также предоставляю детали для iOS:
Android:http://www.cnet.com/how-to/ho-to-pin-apps-in-android-5-lollipop/
я думаю, что есть альтернативное решение без укоренения устройства. Мой босс попросил меня избегать укоренения, поэтому после некоторых исследований я пришел к этому обходному пути. В результате никаких взломов не было сделано, системные ключи все еще остаются, но пользователь не может выйти из приложения и запустить еще один. Итак, я сделал следующие шаги.
1.
При редактировании манифеста установите полноэкранную тему без TitleBar и ActionBar соответствующего Activity, как это: 
<application
    ...
    android:theme="android:Theme.Holo.NoActionBar.Fullscreen" >
2.
Отключена кнопка назад путем переопределения метода Activity класс:
@Override
public void onBackPressed() {
    return;
}
3.
Добавьте следующие строки для манифеста (фильтр намерения соответствующего Activity):
<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>
теперь вы можете заменить домашний экран по умолчанию с вашим приложением. Но возможность выйти из приложения еще остается, нажав на кнопку" последние приложения " и выбрав другой.
4. Чтобы избежать всех других способов выхода из приложения я добавил сервис, который запускается каждый раз, когда действие приостановлено. Эта служба перезапускает приложение и отправляет уведомление о нем. Код сервиса:
public class RelaunchService extends Service {
    private Notification mNotification;
    private Timer mTimer;
    public RelaunchService() {
    }
    @Override
    public void onCreate(){
        super.onCreate();
        if (mNotification == null) {
            Context context = getApplicationContext();
            Intent notificationIntent = new Intent(this, FullscreenActivity.class);
            PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                    notificationIntent, 0);
            Notification.Builder mBuilder = new Notification.Builder(context)
                    .setSmallIcon(android.R.drawable.ic_dialog_info)
                    .setWhen(System.currentTimeMillis())
                    .setContentIntent(contentIntent)
                    .setContentTitle("Your app title")
                    .setContentText("App is being relaunched");
            mNotification = mBuilder.getNotification();
            mTimer = new Timer("LaunchTimer");
        }
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        startForeground(1, mNotification);
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                Intent intent = new Intent(RelaunchService.this, YourActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
            }
        }, 300);
        return START_STICKY;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        stopForeground(true);
        mTimer.cancel();
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
код добавлен в класс Activity:
@Override
protected void onResume() {
    super.onResume();
    exitAllowed = false;
    Intent servIntent = new Intent(this, RelaunchService.class);
    stopService(servIntent);
}
@Override
protected void onPause() {
    super.onPause();
    savePersistentData();
    if (!exitAllowed) {
        Intent servIntent = new Intent(this, RelaunchService.class);
        startService(servIntent);
    }
}
на exitAllowed логическая переменная должна быть задана в true когда вы хотите закрыть приложение. Вы можете рассмотреть какой-то способ сделать это, например, нажав кнопку "Выход". В моем случае для выхода требуется пароль.
некорневое решение возможно в телефоне Samsung, посмотрите на бесплатное приложение Superlock
https://play.google.com/store/apps/details?id=com.superkiosk.ospolice.superlocklite&hl=en_GB
вам не нужно создавать пользовательский ПЗУ или даже корневые устройства, чтобы получить режим киоска. Обычно настоятельно рекомендуется не корневой устройств, которые будут в поле, особенно, если ваши приложения будут иметь конфиденциальные данные.
ответ мыши 12oz (https://stackoverflow.com/a/29560438/2888763) может работать в большинстве случаев, но это не совсем безопасно. Ваше приложение или услуга всегда могут быть убиты системой или сбоем, предоставляя пользователю полный доступ к устройство.
один из способов достижения режима киоска-использовать Google режим блокировки задачи - который отличается от screen-pinning (https://developer.android.com/work/cosu.html). Ссылка там перечисляет некоторые из функций режима задачи блокировки, такие как: наличие одного приложения, прикрепленного к главному экрану, и отключение/скрытие кнопок Home и Recents. Ссылка также показывает, почему самой большой проблемой с решением Google является сложность его настройки. Вы либо должны " использовать стороннее решение enterprise mobility management (EMM)" или "создайте собственное приложение DPC". Решение COSU от Google также может не работать, если у вас нет доступа к сервисам Google Play.
другой вариант-использование мобильной платформы развертывания, такой как Mason (https://bymason.com/), где вы можете создать пользовательскую ОС Android за несколько минут с такими функциями, как режим киоска. Затем можно удаленно развернуть обновления ОС или приложений на всех устройствах.
Не стесняйтесь пинг меня напрямую: trevor @ bymason.com
отказ от ответственности: я работаю на Mason
в конечном итоге я остановился на этом решении, не нуждается в корневых, внешних приложениях и может использоваться в браузерах, webapps и родных приложениях:
захватывающий полноэкранный режим
- используя adb, проверьте, отображается ли ваше устройство с помощью 
adb devices(параметры dev должны быть включены) - найти идентификатор приложения, которое вы хотите в полноэкранном режиме (если это веб-приложение, это браузер, который он использует, как 
org.mozilla.firefoxилиcom.android.chrome) это в play store url:https://play.google.com/store/apps/details?id=org.mozilla.firefox - Excecute в команда 
adb shell settings put global policy_control immersive.full=org.mozilla.firefoxзаменаorg.mozilla.firefoxС вашим id 
подробнее здесь: https://www.howtogeek.com/302194/how-to-force-any-android-app-into-fullscreen-immersive-mode-without-rooting/
в сочетании с закреплением экрана:
- запустите приложение Настройки на вашем устройстве Android.
 - прокрутите вниз, пока не найдете опцию безопасности. Нажмите на него.
 - в нижней части страницы безопасности нажмите на экране пиннинг.
 - сдвиньте переключатель в положение On.
 - Откройте приложение, перейдите в вид с вашими последними приложениями и нажмите значок pin на предварительном просмотре текущего приложения (внизу справа)