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

Имам поглъщаща дейност на цял екран, която трябва да остане на цял екран, докато потребителят изрично излезе. (Например, помислете за нещо като гледане на видеоклип в 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
какви безплатни приложения открадват вниманието ви? когато гледам видео в youtube нищо не изскача   -  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 да бъде сам по себе си статичен, а само променливите. - 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