Is there a way to receive broadcasts(like sms notification) in stopped application?
Actually it works simply in lower than Android 3.1.
EDIT 1:
Thanks to #Squonk for comment.
So my questions is, is it REALLY impossible? you can check PlanB app in market which does this things.
EDIT 2:
this is my broadcast receiver. The onReceive function is never called(when application is stopped).
public class SmsReciever extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
Log.e("kpav", "kpav");
String url = "http://www.google.com";
Intent i = new Intent(Intent.ACTION_VIEW);
i.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(32);
i.setData(Uri.parse(url));
arg0.startActivity(i);
}
}
For Android v3.1 onwards, any app which has been manually started at least once by the user, will receive broadcasts that it has registered in the manifest even after a reboot.
BUT...the user must have manually started that app - it's not possible for an app to be installed and have it automatically receive broadcasts otherwise.
Also, if the user manually uses 'Force Stop' from the Settings on a device, it will no longer receive broadcasts until the user manually starts the app again.
So basically, in answer to your question...
Is there a way to receive broadcasts(like sms notification) in stopped application?
...the answer is no except under the circumstances I describe above.
You can inlcude Stopped Packages to receive broadcasts by simply adding the following flag to the broadcasting intent.
intent.addFlags(32);
Where as 32 refers to Intent.FLAG_INCLUDE_STOPPED_PACKAGES which is available from API level 12.
Related
Before android O, I was able to trigger the functionality of a second sister-app based on the action of a first app. I did this by sending the second app an intent that was defined as a broadcast receiver in the second app. All as well.
But apparently as of api 26, any broadcast receivers defined in the manifest that aren't particular system ones (ie, app specific ones like mine) get ignored. I get errors in the logcat to that effect, I forget the details.
The only way I can think to get this to work is to have the second app start on boot (that broadcast receiver still seems to work) and have it start a service that installs a broadcast receiver programatically, and the service keeps enough of the app alive to receive those messages.
I haven't tried that yet because that seems like overkill and very resource intensive just to receive an intent to do something.
Is there any other mechanism to make this work?
Thanks.
But apparently as of api 26, any broadcast receivers defined in the manifest that aren't particular system ones (ie, app specific ones like mine) get ignored
Not true. You're misunderstanding the restriction.
As of API 26, you can no longer receive implicit broadcasts with a Manifest-declared receiver. However, explicit broadcasts are exempt.
Target the receiver explicitly in your Intent:
Intent intent = new Intent("my_action");
intent.setComponent(new ComponentName("com.sister.packagename", "com.sister.packagename.Receiver");
sendBroadcast(intent);
You'll obviously need to use your own action and the proper package/class name, but that will allow you to keep your Manifest-defined receiver.
Make sure you're checking the action in that receiver's onReceive() method, though. By sending an explicit broadcast, Android ignores your intent filter and sends the intent anyway.
I have an application that installs other applications, just like Google Play Store. To complete the chain of analytics, I need to be able to detect when the apps installed are launched the first time.
Google Play Store definitely has it implemented in some way.
Android system does that for you. The package manager broadcasts Intent.ACTION_PACKAGE_FIRST_LAUNCH to the installer when an installed application is launched for the first time. To make sure you receive it, you need to:
Set the installer package name as soon as you install the application, as the broadcast is restricted to the installer package name set for the application being launched.
getPackageManager().setInstallerPackageName("com.example", getApplicationContext().getPackageName());
Make sure you are not using PackageManager.INSTALL_REPLACE_EXISTING, as it will be assumed to be an update, for which the broadcast is not sent by the system
Register your receiver for action Intent.ACTION_PACKAGE_FIRST_LAUNCH at runtime and not in the manifest.
Registering the broadcast receiver:
registerReceiver(new LaunchReceiver(), new IntentFilter(Intent.ACTION_PACKAGE_FIRST_LAUNCH));
Sample broadcast receiver:
public class LaunchReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getData() != null) {
Log.d(TAG, "Package name: " + intent.getDataString().replace("package:", ""));
}
}
}
For more information, read the actual code here: PackageManagerService.notifyFirstLaunch()
So I have followed this guideline to show a simple toast when SMS is received. While it works ok when app is running, when I go to settings and force-close the app, it stops working.
I checked many answers here on StackOverflow for simmilar questions, but none actually answers whether (and how) it is possible to make a piece of code execute EVERY time SMS is received, without the app being set as the default SMS app on device (Android 4.4+). Is it?
Consider that even service can be stopped, and when that happens, service is not a solution anymore.
I am interested in API level 19+
Thanks
Unfortunately, no, this isn't really possible without your app being the default SMS app.
When the user forcibly closes your app, it is put back into the stopped state, and a statically registered Receiver for the implicit SMS_RECEIVED broadcast won't work until your app has been explicitly started again; e.g., by the user launching your app from an explicit launcher shortcut.
The default SMS app, on the other hand, will be delivered the SMS_DELIVER broadcast, and that is explicit. Even if the default has been forcibly stopped, that broadcast will act like any other explicit starting Intent to bring it out of the stopped state.
If timeliness isn't a major concern, you could just query the SMS Provider as needed – e.g., at each startup – and determine if you've missed any new messages since last checked.
I was making an SMS app. The broadcast would not work when was closed. Tried many things but it didn't work out. Then I decided to change it to the default SMS app by the old code, then the app splash keeps restarting. Then, when I used the following code but it was not working. The dialog box would not show. Then, I found a answer on StackOverflow. Basically you need one activity, TWO receivers and one service. when I added all that to manifest. The default SMS dialog was shown in the app. Which was a success. then I closed the app. my app was receiving the broadcast even when closed. So everything works out pretty well in the end. I hope my experience will help you.
Here is the link How do I set my app as the default SMS app?
void defaultSmsApp(){
RoleManager roleManager;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
roleManager = getApplicationContext().getSystemService(RoleManager.class);
if (roleManager.isRoleAvailable(RoleManager.ROLE_SMS)) {
Log.e(TAG, "defaultSmsApp: " );
if (roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
Toast.makeText(getApplicationContext(), "PrismApp set as default.", Toast.LENGTH_SHORT).show();
Intent i = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
startActivity(i);
} else {
Toast.makeText(getApplicationContext(), "NOT DEFAULT.", Toast.LENGTH_SHORT).show();
Intent roleRequestIntent = roleManager . createRequestRoleIntent (
RoleManager.ROLE_SMS);
someActivityResultLauncher.launch(roleRequestIntent);
}
}
}
}
ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
}
}
});
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 am not able to launch my Broadcast receiver which is part of a STOPPED Application,
I had registered for PACKAGE_ADDED event in the broadcast receiver, The application works properly till 3.0 but above 3.1 I am facing this issue. I used the below lines to send the intent.
Intent intent = new Intent(MY_INTENT_ACTION);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
Please let me know if I need to do anything more.
Adding More Info:
My Intention is i wanted to listen for PACKAGE_ADDED Broadcast event and Perfrom some processing in my OnReceive, Please let me know if there is any possiblity to listen for this event with out launching application. A sample code to achive this would be helpful. Thanks
The docs for PACKAGE_ADDED state:
This is a protected intent that can only be sent by the system.
You can't modify it, or try to add flags to it. From the release notes for 3.1:
Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents.
and from the docs for FLAG_EXCLUDE_STOPPED_PACKAGES
If set, this intent will not match any components in packages that are currently stopped. If this is not set, then the default behavior is to include such applications in the result.
All this means that your app won't work the same way as it used to. You'll have to make sure your app is started in order to receive PACKAGE_ADDED.