What is the most frequently triggered android intent action that my app could have a BroadcastReceiver listening for without a service running in order to receive it?
Background
I have a foreground service that needs to run roughly whenever the user is present at the phone. When the screen gets turned off I shut down the service so Doze mode can be achieved (and yes, foreground running services block Doze mode even though documentation doesn't clearly state so).
The problem comes when trying to turn the service back on.
I've already looked into SCREEN_ON and USER_PRESENT but both appear to require a running background service in order to be received which negates what i am trying to achieve.
So my thought is, I wonder if there's a action triggered frequently enough when the user is present that I could listen for that instead of SCREEN_ON/USER_PRESENT?
I've found that the best way to do this is to register a BroadcastReceiver on the "android.intent.action.USER_PRESENT" action.
To distinguish between cases where the user has turned on his screen when it wasn't locked to when he actually unlocked it use the KeyguardManager to check the security settings.
add this in activity
registerReceiver(new PhoneUnlockedReceiver(), new IntentFilter("android.intent.action.USER_PRESENT"));
and use this :
public class PhoneUnlockedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
KeyguardManager keyguardManager = (KeyguardManager)context.getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager.isKeyguardSecure()) {
//do stuff here
}
}
}
Happy coding!!
Related
I am developing an app and this app needs to give a clear indication to the user when some event happens.
Only thing I could do until now is giving a notification in the notification area. But, I need to give a more visible notification, similar to the behavior when phone is ringing in an incoming call.
As I can understand, the reason why android is only allowing apps to give a notification is to prevent apps from disturbing the user. But, this app I am developing plays a vital role in the job of the user, so I don't think it is inappropriate to give a such strong notification.
I know it should be doable since apps like Viber can start an activity similar to a incoming phone call, even when the device is sleeping.
Does anyone know how to get this done?
Register a broadcast receiver, and add a custom action to it say CustomAction.Instead of showing notification, throw a broadcast and add CustomAction via intent filter.
Now in the onReceive method of broadcast listener, check
if(intent.getAction.equals("CustomAction"))Intent i = new Intent(context, YourActivity);
context.startActivity(i);
Sorry for not a formatted answer, I'm driving, will update it later for more clarification.
Update
Register broadcast receiver in a sticky service. So that service can be started automatically if killed and register broadcast register again.
Don't forget to unregister broadcast receiver in onDestroy() method of service and also in YourActivity when you purpose is resolved.
Just adding a sticky service (which does nothing) fixed the issue. Adding the service prevented the process getting killed when user exits the app and removes it from recent app list.
Because of the service, the app process is running even when a no UI is visible. In this state, if an activity is shown from the GCM service, it gets shown.
You can trigger a broascast as Vinay mentioned. If it still does not work, try using wake-locks. These wake-locks help in waking the device when it is in sleep mode. It will act like force wake and after calling wake-locks, you can perform your actions.
Hope it helped..
Thanks.
I have one app that runs as a service and broadcast receiver with root and device administrator access. I need that app to be able to control the UI for any other app that may be running. For example, I might want to hide the system nav bar or override the home button while other apps are running in the foreground. It is to sandbox the user.
Can anyone suggest how I might do such a thing? Hiding the nav bar in your own app is easy, and of course overriding buttons is no big deal, but I need for one app to be able to do it for other apps.
I'm considering if the UI Automator could help.
My apps (the sandboxer and the other apps that will be running) are mine and they will all have root access. I will also be able to build my own custom version of the Android OS on each device if I need to.
-Thanks
Ok this needs to be done in a two step process,
Create a broadcast from your service
Register a broadcast receiver in your UI application to listen to the broadcasts
In your service do this
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
sendBroadcast(Intent);
In your mainActivity, use
registerReceiver(<receiver instance>, BROADCAST_ACTION)
in the onStart or onCreate method.
This will setup your mainActivity to listen to the broadcasts, next you need to define your broadcast receiver which is the in the above register call.
BroadcastReceiver receiver;
receiver = new BroadcastReceiver() {
public void onReceive(Context c, Intent i) {
//Modify the UI, in this case hide the dialog box.
}
}
I have an application that listens for screen off, and user present intents. Since you cant register to receive screen off intents from the manifest, I am registering them in a service.
Do I really need to have a whole service to ensure that I always get notified of when the screen shuts off, and the user unlocks the phone? Seems really wasteful :-(
The code I use in my service:
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Service created.");
// register receiver that handles user unlock and screen off logic
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
}
You can use a broadcast receiver class. A broadcast receiver can be a stand alone part of an application.
Action_User_Present can be registered in the manifest file.
Please consider what you are broadly trying to do, and a different way to do it.
Yes, the only way to monitor the events is to be actively registered. This is very intentional, because they are a very tempting thing for applications to think they want to be told about, and ending up with a bunch of apps having to be launched each time the user turns their screen on or off would end up with a really bad user experience.
Given that, I can tell you right now that there is no way you can guarantee that you will see these events, besides using a service that is always running and has used startForeground() to prevent itself from being killed. Obviously, this is not something you want to do unless your app is doing something the user very deliberately cares about having running for them when they decide it should be.
So... what are you trying to accomplish?
Since you cant register to receive screen off intents from the manifest
Are you sure about that? The documentation does not describe that limitation, whereas it does for ACTION_BATTERY_CHANGED, ACTION_CONFIGURATION_CHANGED, and ACTION_TIME_TICK.
Please use a manifest-registered BroadcastReceiver if at all possible.
This is some core android code.
mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
| Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
and
mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
We should register filter programmatically when core send with "FLAG_RECEIVER_REGISTERED_ONLY" Flag.
I want to figure out how to detect when the phone wakes up from being in the black screen mode and write a handler for that event. Is that possible? It seems like this would be something a Broadcast Receiver should handle? Or is there a better or more proper way?
If you have a Service that it active you can catch these events with
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do something
}
}, new IntentFilter(Intent.ACTION_SCREEN_ON));
However this relies on having a perpetually running service which I have recently learned is discouraged because it is brittle (the OS likes to close them) and uses resources permanently.
Disappointingly, it seems it is not possible to have a receiver in your manifest that intercepts SCREEN_ON events.
This has come up very recently:
android.intent.action.SCREEN_ON doesn't work as a receiver intent filter
also
Android - how to receive broadcast intents ACTION_SCREEN_ON/OFF?
You could also have a broadcast receiver that catches the USER_PRESENT broadcast intent for when the user has unlocked the device. Naturally some versions of Honeycomb don't honor this but for all non brain-dead versions of Android (2.x and 4.x), it works nicely.
You are right on the broadcast receiver. You could listen to the SCREEN_ON and SCREEN_OFF broadcast events.
I would like to know if it is possible to launch my application whenever a new entry is written to phone call log (i.e. out-going, in-coming or missed call).
I wrote an application to manage the call log entries as per user preferences by listening to the publication of android.intent.action.PHONE_STATE events. My application is working fine as long as its process is running. However if the user has stopped my application with a task-killer application, then the log entries can not be managed as my app itself was not running. I need a way to make sure that my application is launched in the background if it is not already running when the android.intent.action.PHONE_STATE occurs.
Or is it possible to launch my application as a service that always runs?
Thanks in advance.
Bala
You can launch your application as Service:
http://developer.android.com/reference/android/app/Service.html
here is a basic service implementation:
public class MyService extends Service
{
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
Log.i("Service", "Service is starting");
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.i("Service", "Service stopped");
}
}
AndroidManifest.xml
<application ....>
<service android:name=".App.MySyncService" />
</application>
However if the user has stopped my
application with a task-killer
application, then the log entries can
not be managed as my app itself was
not running.
There is nothing that can be done about this. The same thing will occur if the user terminates your service through the Settings > Applications page.
I need a way to make sure that my
application is launched in the
background if it is not already
running when the
android.intent.action.PHONE_STATE
occurs.
You can try setting up a BroadcastReceiver for this Intent in your manifest, and have it route control over to some IntentService for processing. It's the same pattern I use for AlarmManager (sample code here), just with a different trigger. I have not tried this specific Intent, though, so I cannot be certain the technique works. If it does, though, it has a huge benefit of keeping your service out of memory most of the time (IntentService shuts down when its work is complete), which will make your task-killing users happy.
Or is it possible to launch my
application as a service that always
runs?
No, because users are in control over their devices, not you or I.