I can launch my app by:
Tapping on its icon in launcher
Registering "visible" intent-filter (I mean - user clicks for example "Send with.." then chooses my app)
Entering numeral code in dialer and "call" - "invisible" intent, user cannot choose app, he just enters code
Are there any other ways to launch my app? (I'm mostly interested in something else like "invisible" intent from paragraph 3).
Assume that we have clean device only with default system apps (most popular of Google apps are also counted as default) and my app
Ways for usual users are preferred, but more difficult approaches will be also useful
Variants, which can be used on one device (no other devices needed to approach) are preferred, but "more-than-one-device variants" will also be useful.
You can also run your app from Web browser :
<intent-filter>
<data android:scheme="my.special.scheme" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
You can launch your app on NFC transaction :
Into mainfest <uses-feature android:name="android.hardware.nfc" />
Read more about this here : LINK
You can also register a receiver and launch app when you receive sms with secret code in it :
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Object messages[] = (Object[]) bundle.get("pdus");
SmsMessage smsMessage[] = new SmsMessage[messages.length];
for (int n = 0; n < messages.length; n++) {
smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
}
String text = smsMessage[0].getMessageBody();
if(text = "yoursecretcode") {
//launch the app
abortBroadcast(); //if you want to hide this messeage
}
}
Required permission : <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
You can also register a receiver and launch app when you receive call from selected phone number :
public class ServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
MyPhoneStateListener phoneListener=new MyPhoneStateListener();
TelephonyManager telephony = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
}
}
public class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state,String incomingNumber){
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
String numer = TelephonyManager.EXTRA_INCOMING_NUMBER;
// launch your app if 'numer' is ...
break;
}
}
}
You need to this READ_PHONE_STATE permission
You can also use shell to do this (phone must be rooted):
For example :
Runtime.getRuntime().exec("su");
Runtime.getRuntime ().exec ("am start -n com.android.calculator2/.Calculator");
Colleague "Arpan" wrote :
Tilt Your Phone and Wave your Hand (Basically using a Proximity Sensor
to launch App's Intent)
I give you code sample :
public class SensorActivity extends Service implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mProximity;
#Override
public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
}
#Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
}
#Override
public final void onSensorChanged(SensorEvent event) {
float distance = event.values[0];
if(!ss()) // LAUNCH YOUR APP IF ISN't RUNNNING
}
#Override
protected void onResume() {
// Register a listener for the sensor.
super.onResume();
mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
// Be sure to unregister the sensor when the activity pauses.
super.onPause();
mSensorManager.unregisterListener(this);
}
}
private boolean ss() {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if ("com.packagename.something.ActivityName".equals(service.service.getClassName())) {
return true;
}
}
return false;
}
"Arpan" wrote also :
Plug any usb devices and put an intent filter in the manifest (If usb
host mode available)
public static boolean isConnected(Context context) {
Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB;
}
You can paste this to Timer
I have edited Arpan's post, i added link about Gesture Search in Android® .
You can launch application using widget (when user click this, app will launch),
I give you widget class code snipet, more you can find here :
package com.helloandroid.countdownexample;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
public class CountdownWidget extends AppWidgetProvider {
#Override
public void onDeleted(Context context, int[] appWidgetIds) {
//called when widgets are deleted
//see that you get an array of widgetIds which are deleted
//so handle the delete of multiple widgets in an iteration
super.onDeleted(context, appWidgetIds);
}
#Override
public void onDisabled(Context context) {
super.onDisabled(context);
//runs when all of the instances of the widget are deleted from
//the home screen
//here you can do some setup
}
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
//runs when all of the first instance of the widget are placed
//on the home screen
}
#Override
public void onClick() {
//your code to launch application...
}
#Override
public void onReceive(Context context, Intent intent) {
//all the intents get handled by this method
//mainly used to handle self created intents, which are not
//handled by any other method
//the super call delegates the action to the other methods
//for example the APPWIDGET_UPDATE intent arrives here first
//and the super call executes the onUpdate in this case
//so it is even possible to handle the functionality of the
//other methods here
//or if you don't call super you can overwrite the standard
//flow of intent handling
super.onReceive(context, intent);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
//runs on APPWIDGET_UPDATE
//here is the widget content set, and updated
//it is called once when the widget created
//and periodically as set in the metadata xml
//the layout modifications can be done using the AppWidgetManager
//passed in the parameter, we will discuss it later
//the appWidgetIds contains the Ids of all the widget instances
//so here you want likely update all of them in an iteration
//we will use only the first creation run
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}
check if Headphones are plugged in
Whenever Headphones are plugged in an intent (ACTION_HEADSET_PLUG) will be fired. Check for this via BroadcastReceiver and start Acitivity
IntentFilter f = new IntentFilter();
f.addAction(Intent.ACTION_HEADSET_PLUG);
registerReceiver(headsetPlugReceiver, f);
public BroadcastReceiver headsetPlugReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// start new Activity or do something else
}
};
And in Manifest:
<receiver android:name="activity.to.receive.headplug.event">
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
Tilt Your Phone and Wave your Hand (Basically using a Proximity Sensor to launch App's Intent)
Screen Tap And/Or Gesture to launch an intent (you can read about this HERE)
Plug any usb devices and put an intent filter in the manifest (If usb host mode available)
Related
My program purpose: trigger the BACK button in a service
I tried many ways, no one can achieve this purpose, finally I discovered AccessibilityService, it may be the most possible ways to implement this function.
I created this AccessibilityService, and tested it is work
package com.accessibilityservice;
public class MyAccessibilityService extends AccessibilityService {
public MyAccessibilityService() {
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}
#Override
public void onInterrupt() {
}
}
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackSpoken"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="desc"
android:notificationTimeout="100"
android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity" />
And then I tried to move performGlobalAction to service, but it does not perform the action.
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyAccessibilityService mas=new MyAccessibilityService();
mas.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}
}
I also tried to send a custom event in different way, but no one can send to MyAccessibilityService
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//method1
AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_CLICKED);
event.setContentDescription("this is description");
View view = new View(this);
ViewParent parent = view.getParent();
if (parent != null) {
parent.requestSendAccessibilityEvent(view, event);
}
//method2
AccessibilityManager manager = (AccessibilityManager) getApplicationContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
AccessibilityEvent event = AccessibilityEvent.obtain();
event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
event.setPackageName("p");
event.setClassName("c");
manager.sendAccessibilityEvent(event);
}
How can I send a custom event or message to MyAccessibilityService, so that I can recognize the event and message to perform the action?
1 Create a static field of your service
public static MyAccessibilityService instance;
2 then initialize it in onServiceConnected()
#Override
protected void onServiceConnected() {
super.onServiceConnected();
instance = this;
}
3 don't foget to clear it in onUnbind()
#Override
public boolean onUnbind(Intent intent) {
instance = null;
return super.onUnbind(intent);
}
onServiceConnected() is called by the System when user gives permission to your app in device Settings
onUnbind() is when users revokes that permission
4 Use your instance everywhere you want
if(MyAccessibilityService.instance != null)
MyAccessibilityService.instance.performGlobalAction(....)
You can't run an Accessibility service the way in which you are attempting. Accessibility services can only be run as accessibility services. The reason here is obvious, if you understand the capabilities of accessibility services. Things they can do:
Track keyboard events
Investigate contents of text fields
arbitrarily send action events
These can be easily used for malicious purposes. Allowing an application, or even a standard service, to launch a process that can do such things would be terrible security. As such only the system can launch an accessibility service, with all of the relevant permissions. The only place it does this is from the accessibility settings menu. This way users know, at least, when an accessibility service is running, and can be more cautious about the types of these services that they run.
This also leads to the overall answer: You can't. At least not without running an actual accessibility service, and then sending intents directly to that. But the user would have to separately launch your service themselves.
I am not sure if this is the correct way to go but it will get your work done. Have a broadcast receiver registered within your Accessibility service method onServiceConnected() like below.
#Override
protected void onServiceConnected() {
super.onServiceConnected();
registerReceiver(listener, new IntentFilter("my_custom_event_listener));
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(listener);
}
And your broadcast receiver within your accessibility service
private class MyCustomListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if(extras != null){
String action = extras.getString("action");
if(action.equals("back")
performGlobalAction(GLOBAL_ACTION_BACK);
}
}
Instead of creating an event, send a broadcast like below to perform back action:
Intent back = new Intent("my_custom_event_listener");
Bundle data = new Bundle();
data.putString("action", "back");
back.putExtras(data);
sendBroadcast(back);
I've written an android app which checks the network status by using a BroadcastReceiver inherited class:
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d("mylog", "NetworkChangeReceiver Hit");
}
}
which is registered in the manifest file like this:
<receiver
android:name="foo.NetworkChangeReceiver"
android:label="NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
I needed to handle the internet connection whenever it connects or disconnects. Actually, it works perfectly in normal situations.
But the problem is that when the application is closed manually (by minimizing the app and then closing it by swiping out the app icon in the Recents button menu), it still receives the network status changes. This sometimes causes some exceptions.
Even I have included all the code in receiver function in try/catch block, but still sometimes a toast message containing an error message is shown. This sometimes happen even after some days after the closure of the app.
Please note that the code in the receiver function is more complicated than the code that is shown here and has some access to internal classes and variables.
Your app will still receive events, even if it isn't running. Before you do anything in onReceive(), you can check if the activity is running by:
Option 1: Use a static variable in your activity to check it's state for access from the receiver :
public class YourActivity extends Activity {
public static boolean isRunning = false;
#Overrride
public void onCreate(Bundle savedInstanceState){
isRunning = true;
....
}
//We need receiver to work when app is minimized
/*
#Override
public void onStart() {
super.onStart();
isRunning = true;
}
#Override
public void onStop() {
super.onStop();
isRunning = false;
}
*/
}
And in the receiver:
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d("mylog", "NetworkChangeReceiver Hit");
if(!YourActivity.isRunning)
return;
}
}
Option 2 : Using the ActivityManager
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
if (isAppForground(context))
return;
}
public boolean isAppForground(Context mContext) {
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(mContext.getPackageName())) {
return false;
}
}
return true;
}
}
You'll need the permission:
<uses-permission android:name="android.permission.GET_TASKS" />
If you define receivers in your manifest, the app will receive events, even if it is not started.
http://developer.android.com/guide/topics/manifest/receiver-element.html
Broadcast receivers enable applications to receive intents that are broadcast by the system or by other applications, even when other components of the application are not running.
To fix this, just don't define the Receiver in the manifest, but do it programatically in onStart and unregister it again in onStop. The problem with this solution is, that you won't get messages if your app is in the background.
private BroadcastReceiver receiver;
#Overrride
public void onStart(){
super.onStart();
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
filter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
receiver = new NetworkChangeReceiver();
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onStop();
//don't forget to unregister the receiver again
unregisterReceiver(receiver);
}
EDIT: onCreate and onDestroy won't work, as onDestroy will not be called in every instance the app is closed (e.g. if it is closed with the task manager)
Solution Found:
I found a perfect solution to my problem. Thanks to the correct answer in Android service crashes after app is swiped out of the recent apps list, I found out that when an app is closed via Recents list, the whole process will be created again and all the static variables will be freshed to their default values, and the onCreate and all other methods will not be called.
So the solution is something like:
public static boolean appStarted = false;
protected void onCreate(Bundle savedInstanceState) {
appStarted = true;
...
}
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
if (!MyActivity.appStarted)
return;
...
}
}
The key is to just keep track of when the app starts, and not when the app is closed (because the closing event of app is not dependable and in some situations doesn't work properly)
My app has a service that add a floating button to WindowManager.
I want to remove my floating button from WindowManager When user press the power key and turn screen off. So when user turn screen on my floating button does not conceal (mask) android pattern screen lock.
I add following code to my Service but it doesn't work !
Should I add any permission or my service must run in background?!
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
try{
// Remove Floating Button from Window Manager
MyWindowManager.removeView(floating_btn);
// Stop Service
stopSelf();
}
catch (Exception e)
{
//Log Error
}
}
}
}
Normally you would declare a receiver in your manifest. Something like this
<receiver android:name="com.whatever.client.Receiver"
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF" />
</intent-filter>
</receiver>
For some reason (not sure why), you don't seem to be able to do this for SCREEN_OFF or SCREEN_ON. So you have to register it programmatically.
As a test, I made a simple app.
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
startService(new Intent(context, MyService.class));
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(receiver, filter);
}
}
With a simple service.
public class MyService extends IntentService {
public MyService() {
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e("MyService", "Screen was turned off!");
}
}
I've got the same problem and I'm working on it now. In your case it didn't work because 1) your "stopSelf()" have to in class extended by Service, not by BroadcastReceiver. 2) if you want to remove a view from window manager you have to somehow pass(the information of view) that view from that method where you'd declared it to method where you want to remove that view
In creating a watch face for Android Wear, I would like to have a simple configuration (a toggle switch?) that set which mode the user wanted the watch face to looks like (for example, white or black watch face).
I would prefer the toggle switch to be on the watch itself, prefer not to communicate with the phone for such simple action, and hopefully to avoid all the GoogleApiClient communications between watch and phones. Is there a way to do this easily, similar to doing Settings or SharedPreferences on Android?
I tried using a Broadcast receiver. I can get the changes in Broadcast receiver, but how do I get the CanvasWatchFaceService.Engine to update?
Yes, that's possible.
You have to follow this documentation.
First Create an Activity displaying the settings you want the user to change.
Then in your Manifest file, add this meta data to your Watchface service:
<meta-data
android:name=
"com.google.android.wearable.watchface.wearableConfigurationAction"
android:value=
"com.example.android.wearable.watchface.CONFIG_DIGITAL" />
And this IntentFilter to your Activity:
<intent-filter>
<action android:name=
"com.example.android.wearable.watchface.CONFIG_DIGITAL" />
<category android:name=
"com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Of course, you will have to replace "com.example.android" by your package name.
Then a small setting icon will appear below your watchface preview in the Watchface selector screen.
Do not forget to synchronize the setting between your Activity and Watchface in order to make it appear instantly (with a BroadcastReceiver for example)
I addressed this with a LocalBroadcastManager that registers 3 intents
Get Initial Data, sent from Config Activity, expected by Watch Service
Initial Data, sent by Watch Service in response to the message above
Data Changed, sent by Config Activity when user makes selections.
Everything is wrapped in a single class which exposes two interfaces for interactions (one for Watch Service, the other for Config Activity. Probably not the easiest solution but the best I could come up with after 3 days of digging :(
For the record, here is the class sharing 2 variables (bezelMode and time24).
You will need to instantiate it from your watch service (implementing WatchConfig.Service) and you configuration activity (implementing WatchConfig.Editor)
Communication is based on LocalBroadcastManager
public class WatchConfig {
// private static final String TAG = "Config";
// Used when data has changed
public static final String CONFIG_DATA_CHANGED = "/config/changed";
// Used to provide initial data
public static final String CONFIG_INITIAL_DATA = "/config/inital-data";
// Used to query initial data
public static final String CONFIG_INITIAL_QUERY = "/config/initial-query";
private int m_BezelMode;
private boolean m_Time24;
private LocalBroadcastManager localBroadcastManager;
BroadcastReceiver broadcastReceiverDataChanged;
BroadcastReceiver broadcastReceiverInitialDataRequest;
BroadcastReceiver broadcastReceiverInitialData;
private Service service;
private Editor editor;
WatchConfig(Context context, Service service) {
initialize( context, service, null);
}
WatchConfig(Context context, Editor editor) {
initialize( context, null, editor);
}
void initialize( Context context, Service service, Editor editor) {
this.localBroadcastManager = LocalBroadcastManager.getInstance( context);
this.service = service;
this.editor = editor;
}
interface Service {
void onConfigDataUpdated(boolean time24, int bezelMode);
void onConfigInitialRequest();
}
interface Editor {
void onConfigInitialize(boolean time24, int bezelMode);
}
/**
* Registers all proper receivers
*/
public void connect() {
if( this.service != null) {
IntentFilter intentFilterDataChanged = new IntentFilter(CONFIG_DATA_CHANGED);
this.broadcastReceiverDataChanged = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Log.d(TAG,"Data Changed Notification");
service.onConfigDataUpdated(intent.getBooleanExtra("time24", true), intent.getIntExtra("bezel", 24));
}
};
this.localBroadcastManager.registerReceiver(broadcastReceiverDataChanged, intentFilterDataChanged);
IntentFilter intentFilterInitialDataRequesy = new IntentFilter(CONFIG_INITIAL_QUERY);
this.broadcastReceiverInitialDataRequest = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Log.d(TAG,"Initial Query Notification");
service.onConfigInitialRequest();
}
};
this.localBroadcastManager.registerReceiver(broadcastReceiverInitialDataRequest, intentFilterInitialDataRequesy);
} else {
this.broadcastReceiverDataChanged = null;
this.broadcastReceiverInitialDataRequest = null;
}
if( this.editor != null) {
IntentFilter intentFilterInitalData = new IntentFilter(CONFIG_INITIAL_DATA);
this.broadcastReceiverInitialData = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Log.d(TAG,"Initial Data notification");
editor.onConfigInitialize(intent.getBooleanExtra("time24", true), intent.getIntExtra("bezel", 24));
}
};
this.localBroadcastManager.registerReceiver(broadcastReceiverInitialData, intentFilterInitalData);
// Editors need intial data
Intent intentInitialDataRequest = new Intent( CONFIG_INITIAL_QUERY);
this.localBroadcastManager.sendBroadcast( intentInitialDataRequest);
} else {
this.broadcastReceiverInitialData = null;
}
}
public void disconnect() {
if( this.broadcastReceiverDataChanged != null) {
this.localBroadcastManager.unregisterReceiver(this.broadcastReceiverDataChanged);
}
if( this.broadcastReceiverInitialDataRequest != null) {
this.localBroadcastManager.unregisterReceiver(this.broadcastReceiverInitialDataRequest);
}
if( this.broadcastReceiverInitialData != null) {
this.localBroadcastManager.unregisterReceiver(this.broadcastReceiverInitialData);
}
}
/**
* Used to publish changes in configuration
*/
protected void publishInitialData(boolean time24, int bezel) {
this.m_Time24 = time24;
this.m_BezelMode = bezel;
Intent intent = new Intent( CONFIG_INITIAL_DATA);
intent.putExtra("time24", this.m_Time24);
intent.putExtra("bezel", this.m_BezelMode);
this.localBroadcastManager.sendBroadcast(intent);
}
/**
* Used to publish changes in configuration
*/
protected void publishUpdate() {
Intent intent = new Intent( CONFIG_DATA_CHANGED);
intent.putExtra("time24", this.m_Time24);
intent.putExtra("bezel", this.m_BezelMode);
this.localBroadcastManager.sendBroadcast(intent);
}
public void setTime24(boolean time24) {
this.m_Time24 = time24;
}
public void setBezelMode(int bezelMode) {
this.m_BezelMode = bezelMode;
}
}
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.