Держите активность всегда на вершине стека или в фокусе, когда мошеннические приложения запускают действия?

У меня есть полноэкранная иммерсивная активность, которая должна оставаться в полноэкранном режиме до тех пор, пока пользователь явно не выйдет. (Например, подумайте о чем-то вроде просмотра видео на Youtube в полноэкранном режиме).

Однако недавно я заметил, что запуск многих нежелательных действий может нарушить поведение моего приложения. Например, многие сомнительные «бесплатные приложения», как правило, генерируют полноэкранные прозрачные действия и показывают рекламу, немедленно отвлекая пользователя. Всплывающие окна уведомлений «Полноэкранный режим» от определенных приложений, которые на самом деле являются полноэкранными действиями, также мгновенно прерывают мою деятельность.

Есть ли способ избежать кражи фокуса этими действиями или способ удержать их за моей полноэкранной активностью, чтобы они не нарушали мой полноэкранный режим? Другими словами, как мне всегда поддерживать свою активность наверху всякий раз, когда какое-то мошенническое приложение решает запустить активность поверх моей?

Их не нужно отменять, а нужно «отложить на время», пока пользователь не выйдет из полноэкранного режима.

Метод, который приходит на ум, состоит в том, чтобы перезапустить мою активность с FLAG_ACTIVITY_REORDER_TO_FRONT в тот момент, когда она теряет фокус, но это не будет выглядеть красиво для пользователя :(

Примечание. Если вы хотите попробовать это сами, я нашел приложение, которое «симулирует» запуск этих мошеннических действий. Загрузите это - https://play.google.com/store/apps/details?id=com.nlucas.popupnotificationslite&hl=en

Всякий раз, когда вы получаете уведомления, он запускает полноэкранную прозрачную активность. Попробуйте посмотреть видео на Youtube и получить от кого-то 10 уведомлений, и представьте, как это будет отвлекать.

ОБНОВЛЕНИЕ: кажется, что это не работает:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (!hasFocus) {
        Intent i = new Intent(getBaseContext(), MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
        startActivity(i);
}

person Kyle    schedule 07.02.2016    source источник
comment
какие бесплатные приложения отвлекают ваше внимание? когда я смотрю видео на ютубе ничего не появляется   -  person LamaTo    schedule 12.02.2016
comment
Я отредактировал вопрос, чтобы включить эту информацию.   -  person Kyle    schedule 12.02.2016
comment
проблема с onWindowFocusChanged заключается в том, что вы не можете открыть диалог внутри своей активности. вы можете преодолеть это if(! hasFocus && !mDialogList.isShowing()){...   -  person Udi Reshef    schedule 02.08.2016


Ответы (2)


Вы можете запустить службу в фоновом режиме, которая время от времени проверяет, что будет держать ваше приложение на вершине:

public class ServiceKeepInApp extends Service {

//private static boolean sendHandler = false;
KeepInAppHandler taskHandler = new KeepInAppHandler(this);


@Override
public void onCreate() {
    super.onCreate();
    //sendHandler = true;

    taskHandler.sendEmptyMessage(0);
}

@Override
public void onDestroy() {
    super.onDestroy();
    //sendHandler = false;
    taskHandler.removeCallbacksAndMessages(0);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_STICKY;
}

@Override
public IBinder onBind(Intent arg0) {
    return null;
}

private static class KeepInAppHandler extends Handler {
    private final WeakReference<ServiceKeepInApp> mService;
    private Context context;
    private boolean sendHandler = false;

    public KeepInAppHandler(ServiceKeepInApp mService) {
        this.mService = new WeakReference<ServiceKeepInApp>(mService);
        this.context = mService;
        this.sendHandler = true;

    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);

        ActivityManager activityManager = (ActivityManager)context.getSystemService(Service.ACTIVITY_SERVICE);

        if (activityManager.getRecentTasks(2, 0).size() > 0) {
            if (activityManager.getRecentTasks(2, 0).get(0).id != GlobalVars.taskID) {
                activityManager.moveTaskToFront(GlobalVars.taskID, 0);
            }

            if (sendHandler) {
                sendEmptyMessageDelayed(0, 1000);
            }
        }


    }

}

}

Затем создайте одноэлементный класс:

public static class GlobalVars { 
   public static int taskID;
   public static Intent keepInApp;

}

Затем в вашей деятельности:

public class MyActivity extends Activity { 

     @Override
     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         GlobalVars.taskID = getTaskId();

         GlobalVars.keepInApp = new Intent(this, ServiceKeepInApp.class);
         startService(GlobalVars.keepInApp);
     }
}
person Kristy Welsh    schedule 17.02.2016
comment
Вероятно, разумно остановить эту службу в конце процесса, который все время выполняется на переднем плане. Вместо этого перестаньте отправлять сообщения и обратный вызов, верно? Также GlobalVars не обязательно должны быть статическими, только vars. - person Totumus Maximus; 30.09.2016

Лучше всего использовать «закрепление экрана» (как представлено здесь, новое в Android L). Все остальное является хаком или обходным путем, который не будет совместим с предыдущими версиями.

Откровенно говоря, Android на самом деле не был разработан для того, чтобы позволить приложению безоговорочно и полностью завладеть устройством. Android был разработан, чтобы быть инструментом для пользователя, который отвечает на его пожелания. Если они хотят выйти из приложения, почему это должно усложнять это? Кроме того, если пользователь хочет иметь сомнительные приложения, которые неожиданно запускают действия, пусть будет так. Все играют по одним и тем же правилам, установленным системой.

person Doug Stevenson    schedule 19.02.2016
comment
Это потребует от пользователя принятия закрепления экрана, что нежелательно. Это объясняется здесь: android.stackexchange.com/questions/85013/ - person Kristy Welsh; 19.02.2016
comment
Как я уже сказал, то, что вы пытаетесь сделать, нежелательно для конечного пользователя на устройствах общего назначения. Вот почему это требует всех этих дополнительных шагов. Но это средство, которое вам дано. Это вроде взять или оставить это предложение. - person Doug Stevenson; 19.02.2016