I have read here how can I listen to hardware when Activity is in Running state:
#Override
public boolean onKeyDown(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
doSomething();
return true;
}
return super.onKeyDown(keycode, e);
}
I want to use "trigger" button to open/bring forward my app (my MainActivity), if it is in the background (activity stopped) or not running at all (not launched yet or shut down).
Questions:
Can I listen to the hardware keyboard from Android Service and open/bring forward Activity?
How can I do that?
My application is a Barcode/RFID tool that will run on devices like this:
Industrial environment where it will work needs something like "run app immediately and scan" functionality, no matter what is on the screen. Ideally it would be awseome if it could wake up whole device to make warehouse work easier.
This is why I need this.
So at this moment (september 2022) Android Development Guide says, that there are restrictions on starting activities from the background. There are some exceptions.
In my case (inventory management app with dedicated barcode/RFID reader hardware) I should make use of exception for dedicated devices or use some Device Policy Controller:
The app is a device policy controller running in device owner mode.
Example use cases include fully managed enterprise devices, as well as dedicated devices like digital signage and kiosks.
https://developer.android.com/work/dpc/dedicated-devices
However, for development purposes I have tried the AccessibilityService, as suggested here: link
I have added startActivity when the key 293 is pressed (trigger key on device). In comparison to answer linked above - I have choosen diffrent name for service class. Rename has to be done also in XML file.
src/AccessibilityKeyDetectorService.java
public class AccessibilityKeyDetectorService extends AccessibilityService {
private final String TAG = "AccessKeyDetector";
#Override
public boolean onKeyEvent(KeyEvent event) {
Log.d(TAG,"Key pressed via accessibility is: "+event.getKeyCode());
if (event.getKeyCode() == 293)
{
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // this is required to open Activity from service
startActivity(intent);
}
return super.onKeyEvent(event);
}
#Override
protected void onServiceConnected() {
Log.i(TAG,"Service connected");
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
#Override
public void onInterrupt() {
}
}
My res/xml/accessibility_service.xml:
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:settingsActivity=""
android:packageNames="pl.globalsystem.rflow"
android:canRequestFilterKeyEvents="true" />
And my manifest entry:
<service android:name=".services.AccessibilityKeyDetectorService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="#xml/accessibility_service" />
</service>
And my MainActivity method for accessibility permissions:
public boolean checkAccessibilityPermission() {
int accessEnabled=0;
try {
accessEnabled = Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
if (accessEnabled==0) {
/** if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
/** request permission via start activity for result */
startActivity(intent);
return false;
} else {
return true;
}
}
Related
I have developed small app to detect changes in network like on, off or connection change Wifi to Ethernet, whenever app closed or running in all cases.
Provided code working for me upto Nuget 7, when testing app in Oreo 8 background services not working when app terminated.
How can I get it work in Oreo?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
Intent vpnServiceIntent = new Intent(getBaseContext(), MyService.class);
startForegroundService(vpnServiceIntent);}}
WifiReceiver.java file
public class WifiReceiver extends BroadcastReceiver {
static final String CONNECTIVITY_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (CONNECTIVITY_CHANGE_ACTION.equals(action)) {
if (!isConnected()) {
if (context != null) {
Toast.makeText(context," Not connected...",Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(context,"connected...",Toast.LENGTH_LONG).show();
}
}
}
}
MySevice.java file
public class MyService extends Service
{
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
WifiReceiver receiver =new WifiReceiver();
registerReceiver(receiver,filter);
return START_STICKY;
}
}
Manifest.xml file
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
<receiver android:name=".WifiReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<service android:name=".MyService" />
</application>
Note: If I call startForeground(101, notification); in onCreate of MyService class, my above code is working but showing permanent notification icon on top most status bar, that I don't want at all.
since Android 8.0 (API level 26) it is basically impossible to run background service while app is not visible because of Battery optimizations and security reasons.
It sucks, many useful apps can not run and work normally.
They recommend to use ForegroundService which requires to show notification.
It would be almost okay, but these ForegroundServices also gets killed after some time.
To avoid killing them you need to make BatteryOptimization prompt so user would let service running in background without killing.
But it is not over yet... Services is still being killed on most of Manufactures like Samsung, Huawei and so on because they has they own badly implemented BatteryOptimizations running parallel with native one... and if user want some app avoid to be killed while running in background it has to go long way to settings find provider specific settings and let app run....
here is an example how to change these provider specific settings on Slack
I think it is worst thing that happened to Android.....
I have an Android App with working Auto capabilities which has been rejected from the store because:
"Your app does not support all of the required voice commands.
For example, your app does not contain an Intent filter for action "android.media.action.MEDIA_PLAY_FROM_SEARCH"."
So i looked to at least make the app respond to "play music on X app" but by looking at the documentation I can't get it to work. I added this to my main activity (which is not the launcher activity, it controls the service via binder)
<intent-filter>
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
which triggers a MediaBrowserServiceCompatwhich is initialized this way:
manifest:
<service
android:name=".Services.RadioService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
part of the code:
#Override
public void onCreate() {
super.onCreate();
audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
mSession = new MediaSessionCompat(this, "RService");
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
| MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
mSession.setCallback(mCallback);
mSessionConnector = new MediaSessionConnector(mSession);
setSessionToken(mSession.getSessionToken());
setMediaBrowser();
initializeReceiver();
C_F_App.createNotificationChannelPlayer(getApplicationContext());
rNController = new RadioNotificationController(this, mSession, getApplicationContext());
}
final MediaSessionCompat.Callback mCallback =
new MediaSessionCompat.Callback() {
#Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
playForAuto(mediaId);
}
#Override
public void onPlayFromSearch(String query, Bundle extras) {
super.onPlayFromSearch(query, extras);
Log.d("Test", "Test");
}
#Override
public void onStop() {
playPause();
}
#Override
public void onPlay() {
playPause();
}
#Override
public void onPause() {
playPause();
}
};
public void setMediaBrowser() {
mediaBrowser = new MediaBrowserCompat(getApplicationContext(),
new ComponentName(getApplicationContext(), this.getClass()),
new MediaBrowserCompat.ConnectionCallback() {
#Override
public void onConnected() {
super.onConnected();
}
#Override
public void onConnectionSuspended() {
super.onConnectionSuspended();
}
#Override
public void onConnectionFailed() {
super.onConnectionFailed();
}
}, null);
mediaBrowser.connect();
}
#Override
public long getSupportedPrepareActions() {
return PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID |
PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID |
PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH |
PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH;
}
Auto capabilities work fine.
When i try to call this app on Auto from the emulator to play music it just does't do anything, it does not say errors or other stuff, it just closes google speak and then returns to the normal display. The method onPlayFromSearch is never called and it should be the one Auto would call if a voice command is sent.
Can someone help me figure out what i'm doing wrong? Google doc is pretty useless this way, Google UAP doesen't look to have this capability like the old version but looking at the old UAP version i cannot figure out what I'm doing wrong.
PS. The app is not published yet with this functionality
Thanks in advance.
To clear the review process, you’ll only need to get “Play X” (while the app is running in the foreground) working. After adding the intent filter, and if the app handles the search query while its running, I’d kick off another app review.
Otherwise, I believe it’s more of a Google Assistant feature that handles “Play X on Y” when the app is not in the foreground. I don’t have all the details on this, but the assistant may be querying their servers for the app name and package. If it isn’t published yet, it may not work locally.
EDIT
The best way to test your intent filter to clear the app review is to call the intent from adb on the mobile device with:
adb shell am start -a android.media.action.MEDIA_PLAY_FROM_SEARCH
If your app appears in the following media list drawer, the intent filter is setup correctly. You should then see the onPlayFromSearch "Test" log fire when "Play music" is sent while the app is running on Android Auto via the Desktop Head Unit.
I've got an app that registers itself as the default launcher and pins itself automatically when started.
This all works fine when installing the app. It pins itself and only the back button is visible.
The problem is that when the device first boots up, it does not pin properly. I see a series of toasts "Screen pinned" and "Screen unpinned" multiple times. The "Home" and "Recent Tasks" buttons are still visible as well.
--
Running "adb shell dumpsys activity activities" - the last lines indicate that it is not pinned:
mLockTaskModeState=NONE mLockTaskPackages (userId:packages)=
0:[com.example.myapp]
mLockTaskModeTasks[]
--
Testing device Asus ZenPad running Marshmallow/6.0/23
I'm relying on the MainActivity manifest attribute "lockTaskMode" to pin (rather than 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>
Any help or pointers would be appreciated
I had the same problem and I could really only find one solution. I'm not sure why but yeah, something in android prevents task locking when booting up which boggles my mind since the task lock was designed to create these "kiosk" type of applications. The only solution I could find was to detect for a case when it didn't lock then restart the application. Its a little "hacky" but what else can you do?
To detect for the case where it didn't lock I created a state variable and assigning states (Locking, Locked, Unlocking, Unlocked). Then in the device admin receiver in onTaskModeExiting if the state isn't "Unlocking" then I know it unlocked on its own. So if this case happened where it failed, I then restart the application using this method (which schedules the application in the alarm manager then kills the application):
how to programmatically "restart" android app?
Here is some sample code:
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;
}
MainActivity
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();
}
}
In truth this is a simplified version of what I implemented. But it should hopefully get you pointed towards a solution.
The only solution I found as for now : make another launcher app, without locktask, which will trigger main app every time when launcher appears. This prevent user for waiting few more seconds before LockTasked app is being called with on BOOT_COMPLETED receiver. So we can meet this problem only when lockTask app has launcher properties for some activity in manifest.
Sorry for late answering, but...
Anyone has this problem can do this tricky work in first (LAUNCHER/HOME) activity (e.g. 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
}
I have a android application that is trying to use the new NotificationListenerService class from api 18. I have created my own service class that inherits from this class and overrode the onNotificationPosted and onNotificationRemoved events and although my service seems to start just fine these 2 events never seem to be called when I get or remove a notification.
Has anyone had any success with this class or possibly any source code they are will to share demonstrating exactly how to use this class?
In my experience, almost all of these answers are so damn close to the right solution!
The CORE problem seems to happen during development; as you are developing your code the "Notification access" settings stop being honored when you update your app between debug sessions.
If your APK/binary changes and your NotificationListenerService stops:
Rebooting fixes it.
Going back in to "Notification access" and disabling and re-enabling your app it fixes it.
Hopefully this isn't a problem when updating your app through Google Play.
As a best practice, for my app I add an overflow menu option that only shows up in non-release builds that allows me easy access to the settings:
NotificationListener.java:
public class NotificationListener
extends NotificationListenerService
implements RemoteController.OnClientUpdateListener
{
private static final int VERSION_SDK_INT = VERSION.SDK_INT;
public static boolean supportsNotificationListenerSettings()
{
return VERSION_SDK_INT >= 19;
}
#SuppressLint("InlinedApi")
#TargetApi(19)
public static Intent getIntentNotificationListenerSettings()
{
final String ACTION_NOTIFICATION_LISTENER_SETTINGS;
if (VERSION_SDK_INT >= 22)
{
ACTION_NOTIFICATION_LISTENER_SETTINGS = Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS;
}
else
{
ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
}
return new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS);
}
...
}
menu_my_activity.xml:
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MyActivity"
>
<item
android:id="#+id/action_application_info"
android:title="#string/action_application_info"
app:showAsAction="never"
/>
<item
android:id="#+id/action_notification_settings"
android:title="Notification Settings"
app:showAsAction="never"
/>
</menu>
MyActivity.java:
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.menu_my_activity, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu)
{
MenuItem menuItem;
menuItem = menu.findItem(R.id.action_application_info);
if (menuItem != null)
{
menuItem.setVisible(BuildConfig.DEBUG);
}
menuItem = menu.findItem(R.id.action_notification_settings);
if (menuItem != null)
{
menuItem.setVisible(BuildConfig.DEBUG && NotificationListener.supportsNotificationListenerSettings());
}
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.action_application_info:
startActivity(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName())));
return true;
case R.id.action_notification_settings:
startActivity(NotificationListener.getIntentNotificationListenerSettings());
return true;
default:
return super.onOptionsItemSelected(item);
}
}
After installing a app configured properly, you should grant it.
You can find the name of the app at "Settings > Security > Notification access", then be sure the check box is filled. :)
update: https://gist.github.com/xinghui/b2ddd8cffe55c4b62f5d8846d5545bf9
private void toggleNotificationListenerService() {
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(this, com.xinghui.notificationlistenerservicedemo.NotificationListenerServiceImpl.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(new ComponentName(this, com.xinghui.notificationlistenerservicedemo.NotificationListenerServiceImpl.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}
adb shell dumpsys notification
check which service is living.
com.android.server.notification.ManagedServices#rebindServices
toggleNotificationListenerService() trigger system invoke this method.
I have encountered this bug:
https://code.google.com/p/android/issues/detail?id=59044
And notifications started coming to my service only after I rebooted my phone.
After many hours of researching, I finally found sample code that actually works:
https://github.com/yihongyuelan/NotificationListenerServiceDemo
After debugging multiple times to a device, renaming your NotificationListener class helps fix the problem. It doesn't matter what you rename it to, just changing it to something different from the previous name. I've always had to do this over and over again.
Sometimes deleting build and rebuilding source might be the issue.
I Struggled with it for 3 days, and here is what I have done:
AndroidManifest.xml
Changes service name from just class example:
<service
android:name=".NotificationListener"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
to
<service
android:name="com.mypackage.example.NotificationListener"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
Navigate to your root directory > android , then delete build folder, allow your project to rebuild.
NLService will be working all the time as per android docs but in some cases it will be unbind from your specific app and may restarting your phone it will bind again . But in safer side you can have this check whenever your starts ,
// check NLsettings
private void checkNLSettings() {
//check notification access
if (!NotificationUtils.isNotificationServiceEnabled(this)) {
//start NLsetting activity
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivityForResult(intent, REQUEST_ACCESSIBLITYCODE);
finish();
}
//check isNLservice running
if (!isNLServiceRunning()) {
enableNotificationListenerService(this);
}
Toast.makeText(this, "NLS == " + isNLServiceRunning(), Toast.LENGTH_SHORT).show();
}
private boolean isNLServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service :
manager.getRunningServices(Integer.MAX_VALUE)) {
if (NLService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
/**
* enable notification service.
*
* #param context context
*/
public static void enableNotificationListenerService(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
NotificationListenerService.requestRebind(new ComponentName(context.getPackageName(),
COMPONENT_NLSERVICE));
} else {
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(context.getPackageName(),
COMPONENT_NLSERVICE),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
}
I have just come accross a great little example of this class in action:
http://www.kpbird.com/2013/07/android-notificationlistenerservice.html
One thing I learned from following this example is that the notification service I created starts automatically when permission is granted via the new notification access screen, meaning my application doesn't have to start the service manually.
I'm using C2DM, my BroadcastReceivers propagate the C2DM events to a local service. the service complete the registration by sending the id to my webserver pus it's responsible for letting the device know about new messages, however if the application (one of the activities) is up we want to send an intent to that activity with the new data so it can be updated, if not than the NotificationManager is used to notify the user.
The issue is, how to know the activity is running ? the Application object is not an option since the Service is part of the application it's obviously going to be present. unregister in the onDesroy of each application is also not an option since it may occur in orientation change...
Any standard way to get it done ?
Solution 1:
You can use ActivityManager for Checking if Activity is Running or not:
public boolean isActivityRunning() {
ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> activitys = activityManager.getRunningTasks(Integer.MAX_VALUE);
isActivityFound = false;
for (int i = 0; i < activitys.size(); i++) {
if (activitys.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.example.testapp/com.example.testapp.Your_Activity_Name}")) {
isActivityFound = true;
}
}
return isActivityFound;
}
need to add the permission to your manifest..
<uses-permission android:name="android.permission.GET_TASKS"/>
Solution 2:
Your can use an static variable in your activity for which you want to check it's running or not and store it some where for access from your service or broadcast receiver as:
static boolean CurrentlyRunning= false;
public void onStart() {
CurrentlyRunning= true; //Store status of Activity somewhere like in shared //preference
}
public void onStop() {
CurrentlyRunning= false;//Store status of Activity somewhere like in shared //preference
}
I hope this was helpful!
The next approach would work well if you want to handle incoming Google Cloud message (C2DM) by your activity (if any is running) or issue a notification if no activities are running.
Register one BroadcastReceiver in the manifest file. This receiver will handle C2D messages whenever application not running. Register another BroadcastReceiver programmatically in your activity. This receiver will handle C2D messages whenever activity is running.
AndoroidManifest.xml
<receiver
android:name=".StaticReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.mypackage" />
</intent-filter>
</receiver>
MyReceiver.java
public class StaticReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Trigger a Notification
}
}
MyActivity.java
public class MyActivity extends ActionBarActivity {
#Override
protected void onResume() {
super.onResume();
final IntentFilter filter = new
IntentFilter("com.google.android.c2dm.intent.RECEIVE");
filter.addCategory("com.mypackage");
filter.setPriority(1);
registerReceiver(dynamicReceiver, filter,
"com.google.android.c2dm.permission.SEND", null);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(dynamicReceiver);
}
private final BroadcastReceiver dynamicReceiver
= new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Handle C2DM
// blocks passing broadcast to StaticReceiver instance
abortBroadcast();
}
};
}
Note! To catch broadcasts first, the priority of dynamicReceiver IntentFilter must be higher than priority of StaticReceiver instance IntentFilter (default priority is '0').
PS. It looks like broadcasts issued by Google Cloud Messaging Service are ordered broadcasts. Original idea author: CommonsWare
Copied from here.
you can use a static variable within the activity.
class MyActivity extends Activity {
static boolean active = false;
public void onStart() {
active = true;
}
public void onStop() {
active = false;
}
}
Easiest way to check that whether an Activity is running or not is:
Context context = MyActivity.this;
if (! ((Activity) context).isFinishing()) {
// Activity is running
} else {
// Activity has been finished
}
Note: If activity is not running you should not perform any UI related operation.