I have an Android app that handles plug-ins of my specific storage device. I want to be able to show the contents of the storage device in a specific way with my Display activity when the device is mounted on the system. The problem I'm having is that on some phones the system also handles the ACTION_MEDIA_MOUNTED broadcast and then automatically brings up the Android file explorer (which takes the screen away from my app). This is what I am trying to prevent if at all possible. I am registering a broadcast receiver to listen for the ACTION_MEDIA_MOUNTED broadcast and then starting my Display activity as soon as I receive this broadcast like so:
BroadcastReceiver mediaMountedReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("debug", "HEAR YE! HEAR YE! THE MEDIA HAS BEEN MOUNTED!");
if (isOrderedBroadcast()) {
abortBroadcast();
}
Intent i = new Intent(getApplicationContext(), Display.class);
startActivity(i);
}
};
...
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addDataScheme("file");
filter.setPriority(999);
registerReceiver(mediaMountedReceiver, filter);
I receive the broadcast alright and I try to cancel it by calling abortBroadcast() but apparently ACTION_MEDIA_MOUNTED is not an ordered broadcast. Is there any way to stop propagation of this broadcast or to direct all storage mount/unmount broadcasts to my app?
If this is not possible does anyone have tips or workarounds on how to deal with this?
Related
I am trying to work with an android broadcast receiver, which i want to be invoked upon completion of BT file transfer (in case of receiving file).
Use Case :
Device (A) is already paired with another Bluetooth enabled device (B) and when B sends a file to device A, I want my broadcast receiver to execute.
Is there any way to achieve it?
I tried filtering for below events, but it seems to be private events of default Bluetooth app and is intented only for BluetoothShare component that pushes the notification on completion of file reception and NOT broadcasted publicly. As a result, my broadcast receiver is NOT invoked real device with actual file transfers but when I send any of the below intent from ADB shell its working in both emulator and real device.
Intents filtered in AndroidManifest.xml:
"android.btopp.intent.extra.**BT_OPP_TRANSFER_STATUS**"
"android.btopp.intent.action.**BT_OPP_TRANSFER_DONE**"
"android.intent.action.**DOWNLOAD_COMPLETE**"
Any leads would be greatly appreciated.
Thanks
You can monitor the Connectivity action of Bluetooth. There is a connecting action when the device begin to receive file and when its compeleted there will be a disconnecting action. You can register for ACTION_ACL_DISCONNECTED and onReceive take some action
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == BluetoothDevice.ACTION_ACL_DISCONNECTED) {
}
}
}
Register receiver as follows:
IntentFileter blutoothFilter= new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiver, blutoothFilter);
I'm developing an app which needs to run some code (Networking) whenever an SMS is received.
In API 25 and lower it's fine, I register an implicit receiver in Manifest file and start my service in the specified class which extended BroadcastReceiver. In API 26 however you cannot register android.provider.Telephony.SMS_RECEIVED in a receiver since it won't work.
From Android documentation:
Note: If your app targets API level 26 or higher, you cannot use the manifest to declare a receiver for implicit broadcasts (broadcasts that do not target your app specifically), except for a few implicit broadcasts that are exempted from that restriction. In most cases, you can use scheduled jobs instead.
I've read several articles like this one on medium. There are solutions like JobScheduler or Explicit Receiver, however the first one is used for changes in network state and I couldn't find a way to trigger the job on SMS_RECEIVED event and the second one is valid until your activity is up and running.
Because of the nature of my application I need to listen for incoming SMS whether the app is running or not. How to do that in API 26+?
Edit
Maybe the code in JobInfoBuilder doc on android website could help. It monitors the changes in the photos on a device and start the job on change. However I cannot find a proper Uri to do the same with the SMS (not even sure if it's possible to monitor SMS via ContentObserver)
Since there are lots of ways to do the job in android O, I post this answer and mention my approach to solve the problem. Obviously by problem I mean the general problem not the SMS_RECEIVED receiver itself.
I start a foreground service and in there I register a dynamic or explicit receiver to listen to the incoming calls (for instance):
In MainActivity.java:
String action = "START"
final Intent intent = new Intent(this, CallMonitorService.class);
intent.setAction(action);
startService(intent);
In CallMonitorService.javas onCreate() method where I have BroadcastReceiver callExplicitReceiver as a field:
final IntentFilter intentFilter = new IntentFilter();
intentFilter.setPriority(2147483647);
intentFilter.addAction("android.intent.action.PHONE_STATE");
this.callExplicitReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
// do the stuff here
}
}
};
registerReceiver(callExplicitReceiver, intentFilter);
and then in onStartCommand():
if (intent.getAction().equals("START")) {
Intent callServiceNotificationIntent = new Intent(this, MainActivity.class);
callServiceNotificationIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent
.getActivity(this, CALL_SERVICE_REQUEST_CODE,
callServiceNotificationIntent, CALL_SERVICE_FLAG);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(CALL_NOTIFICATION_CONTENT_TITLE)
.setTicker(CALL_NOTIFICATION_TICKER)
.setContentText(CALL_NOTIFICATION_CONTENT_TEXT)
.setSmallIcon(R.drawable.ic_info_outline_black_24dp)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
startForeground(CALL_NOTIFICATION_ID, notification);
}
and finally:
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(callExplicitReceiver);
}
I think of this as a good approach since the user is notified of the running service because of the undismissable notification and that's what android Oreo wants, however through a button in the app user could stop the service and the monitoring receiver as a direct result of destroying service (I cleared that part of code).
I think for now you are safe as SMS_RECEIVED_ACTION is present in the current exempted implicit broadcast list. Also, upon receiving the system broadcast you can either start a foreground service or schedule a job (to perform network operation in your case). Moreover, I am also using the same action and upon testing it seems to work okay.
I registered receiver in onCreate, but onReceive sometimes get called, sometimes not.
public class MyReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.v("receiver","get called");
}
}
Here is how I register receiver in onCreate
PROCESS_RESPONSE = getBaseContext().getResources().getString(R.string.serviceResponse);
IntentFilter filter = new IntentFilter(PROCESS_RESPONSE);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new MyReceiver();
registerReceiver(receiver, filter);
Here is how I send broadcast:
Intent broadcastIntent = new Intent();
PROCESS_RESPONSE=getBaseContext().getResources().getString(R.string.serviceResponse);
broadcastIntent.setAction(PROCESS_RESPONSE);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(broadcastIntent);
Try this:
broadcastIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
The reason it sometimes works and doesn't work is
because Android 3.0 introduced a launch control security measure that prevents components of stopped applications from being launched via an intent. An application is considered to be in a stopped state if the application has either just been installed and not previously launched, or been manually stopped by the user using the application manager on the device. To get around this, however, a flag can be added to the intent before it is sent to indicate that the intent is to be allowed to start a component of a stopped application.
Quote source
So when you try a fresh install (launching from IDE) the application is considered in the stop state for a while, then later is not. So it sometimes doesn't work when you try to broadcast. Let me know if this works, and of course ensure you have registered the BroadcastReciever (I'm sure you have if it works, at least some of the time).
I need to send broadcast from my one application to another applicaion.. any help!
my application package are 1)com.demo.database and 2)com.demo.list
Intent themesIntent = new Intent(ThemesManager.THEMES_UPDATED);
themesIntent.putExtra("package", packageName);
ctx.sendBroadcast(themesIntent);
not working..
Edits :
<receiver android:name="com.sample.ThemesUpdatedReceiver">
<intent-filter>
<action android:name="com.sample.THEMES_UPDATED"/>
</intent-filter>
</receiver>
#Ajit: Hi, Since Android API 3.0 [API level 11], If an application has never been started even once, then it's BroadcastReceiver can't receive events.As, in your case, your app has no launcher activity, so may be it is the case that causes rejection of event.
Along with that please try using below approach:
You have passed that constant value while creating Intent object. Instead pass it in method intent.setAction();
Hope this helps.
I figured that every sent broadcast is received by all applications except when you setPackage to the sending intent for specific package broadcast.
I am not receiving broadcast because my another app is not launched(that doesn't have launcher activity).
If you're going to broadcast, it generally follows you have a sender and receiver. You've posted what looks like the sender ..
sender (where ever you're sending from):
Intent toret = new Intent();
toret.setAction("com.myapp.foo");
toret.putExtra("bar", "fizzbuzz");
sendBroadcast(toret);
receiver (in eg onResume())
IntentFilter intentFilter = new IntentFilter("com.myapp.foo");
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// ... do something with the intent
}
// register the receiver
this.registerReceiver(receiver , intentFilter);
Sender always sends, receiver needs to register to listen for the intent.
I have an app in which the main Activity starts an AlarmReceiver that calls an IntentService that runs in the background and does stuff. I'm unclear on what the correct way is to check on the IntentService's actions and present the end-user with some feedback in the visible Activity that they're in, on the IntentService's current state. In my ideal world there can be an icon somewhere on the screen that I can set to notify the user of what's going on with the IntentService. I don't need the user to be able to *do anything, just have feedback.
All advice welcome.
Android has a notification API, which is even easy to use - Creating Status Bar Notifications.
If you want your activity to receive updates from the service, I would suggest using broadcasts and broadcast receivers.
How to send a broadcast intent:
Intent i = new Intent("your.action");
sendBroadcast(i);
To receive this broadcast within your activity, you have to implement a broadcast receiver:
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//
}
};
which you have to register...
registerReceiver(myReceiver, new IntentFilter("your.action"));