Проверьте, открыто ли приложение во время события GCM onMessage?

Мне интересно, как проверить, открыто ли мое приложение и в настоящее время видно пользователю при получении onMessage() из GCM. Сначала я просто использовал свой собственный boolean isVisible, но потом понял, что это ненадежно, потому что, если приложение не открыто, объект, который я использую для доступа к этому флагу, null. Хотя это само по себе можно было бы использовать, чтобы узнать, открыто ли приложение, это кажется немного беспорядочным. Есть ли способ в Android с системного уровня, чтобы как-то проверить, открыто ли приложение в данный момент, и если пользователь просматривает приложение? Имейте в виду, что приложение может быть запущено, но не видно, потому что пользователь недавно нажал кнопку "домой", отправив его на задний план.

@Override
protected void onMessage(Context arg0, Intent arg1) {
    String turn = intent.getExtras().getString("turn");
    if (turn.equals("yours"){
         if (/*app is open*/){ <------------------ what can go here?
             // dont generate a notification
             // display something in the game instead
         }
         else{
             // generate notification telling player its their turn
         }
    }
}

Ответ 1

Я бы использовал для этого широковещательные передачи заказов.

В вашем методе onMessage:

Intent responseIntent = new Intent("com.yourpackage.GOT_PUSH");
sendOrderedBroadcast(responseIntent, null);

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

public class YourActivity extends Activity {

    final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            //Right here do what you want in your activity
            abortBroadcast();
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //.....
    }

    @Override
    protected void onPause() {
        unregisterReceiver(mBroadcastReceiver);
        super.onPause();
    }

    @Override
    protected void onResume() {
        IntentFilter filter = new IntentFilter("com.yourpackage.GOT_PUSH");
        filter.setPriority(2);
        registerReceiver(mBroadcastReceiver, filter);
        super.onResume();
    }
}

Другой BroadcastReceiver

public class SecondReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //In this receiver just send your notification
    }

}

манифеста:

<activity
    android:name=".YourActivity"
    android:label="@string/app_name">
    <intent-filter>
        <action
            android:name="android.intent.action.MAIN" />
        <category
            android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<receiver
    android:name=".SecondReceiver">
    <intent-filter
        android:priority="1">
        <action
            android:name="com.yourpackage.GOT_PUSH" />
    </intent-filter>
</receiver>

В основном в методе onMessage вы отправляете Intent, который сначала принимается BroadcastReceiver, зарегистрированным внутри YourActivity, если он запущен и на переднем плане, в противном случае он принимается SecondReceiver.

Ответ 2

Используйте SharedPreferences, сохраняя значение boolean isVisible, и когда вы получите значение из этой настройки, вы можете добавить значение по умолчанию.

SharedPreferences settings = context.getSharedPreferences("NAME_XXX", Activity.MODE_PRIVATE);
settings.getBoolean("visible", false);

Ответ 3

То, что я всегда делаю, это ссылка на текущую активность.

Я устанавливаю текущую активность в каждом onResume и устанавливаю ее в значение null в каждом onPause.

Если текущая активность равна нулю, приложение не открыто. Если он не является нулевым, вы можете увидеть, открыта ли правильная активность и доставить ее в эту операцию.

GCMIntentService:

public static Activity currentActivity;
public static final Object CURRENTACTIVIYLOCK = new Object();

    @Override
protected void onHandleIntent(Intent intent) {
    synchronized(CURRENTACTIVIYLOCK) {
        if (currentActivity != null) {
            if (currentActivity.getClass() == CorrectActivity.class) {
                CorrectActivity act = (CorrectActivity)currentActivity;
                act.runOnUiThread(new Runnable() {
                    public void run() {
                        // Notifiy activity
                    }
                });
            } else {
               // show notification ?
            }
        } else {
            // show notification
        }
    }
}

CorrectActivity:

@Override
    protected void onResume() {
        synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
                GCMIntentService.currentActivity = this;
            }
        }
        super.onResume();
    }

@Override
    protected void onPause() {
        synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
            GCMIntentService.currentActivity = null;
        }
        super.onPause();
    }

Ответ 4

То, что сработало для меня:

Создайте окончательные константы класса, внутри него, создайте статические varaiable:

public final class Constants{
public static AppCompatActivity mCurrentActivity;
}

Теперь, по каждому из резюме ваших действий говорим:

    @Override
    protected void onResume() {
        super.onResume();
        Constants.mCurrentActivity = this;
    }

При получении уведомления проверьте, является ли текущая активность нулевой, если ее нулевое приложение не открыто, если активность не равна нулю, вы можете проверить такие вещи, как:

if(Constants.mCurrentActivity instanceof MainActivity){
   ((MainActivity) Constants.mCurrentActivity).yourPublicMethodOrStaticObject;
}