I want to allow other Apps to integrate with mine and I'm writing a dummy "consumer" app but I cant achieve to return a callback to notify the "consumer" app if everything went well.
So my DUMMY_APP has a simple layout with 2 buttons a success call, and a call with a wrong EXTRA param.
To make DUMMY_APP to call MAIN_APP I use sendBroadcast
// MainActivity class
private static final String REQUIRED_ACTION = "com.basetis.afr.intent.action.INIT_TEXT_FLOW";
onCreate....
Button btnSuccess = (Button)findViewById(R.id.button_success_call);
btnSuccess.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
i.setAction(REQUIRED_ACTION);
i.putExtra(Intent.EXTRA_TEXT, textToBeRead);
sendBroadcast(i);
}
});
So MAIN_APP has the corresponding BroadcastReceiver that is receiving fine.
// BlinkingReadReceiver class
private static final String CALLBACK_CALL_AFR_ACTION = "com.basetis.afr.intent.action.CALLBACK_CALL_AFR_ACTION";
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent();
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Log.d(TAG, "SUCCESS send callback");
i.setAction(CALLBACK_CALL_AFR_ACTION);
i.putExtra(CALL_AFR_SUCCESS_EXTRA, CALL_AFR_SUCCESS_EXTRA_DESC);
i.setType("text/plain");
context.sendBroadcast(i);
}
So the DUMMY_APP BroadcastReceiver never receive nothing :(
So I configured Manifests like that:
DUMMY_APP
<receiver android:name=".MainBroadcastReceiver" android:enabled="true">
<intent-filter>
<action android:name="com.basetis.afr.intent.action.CALLBACK_CALL_AFR_ACTION"></action>
</intent-filter>
</receiver>
MAIN_APP
<receiver android:name=".BlinkingReadReceiver" android:enabled="true">
<intent-filter>
<action android:name="com.basetis.afr.intent.action.INIT_TEXT_FLOW"></action>
</intent-filter>
</receiver>
Sometimes I receive this error (afrsender is de DUMMY_APP) but seems sort of random...
Performing stop of activity that is not resumed: {com.basetis.afrsender.afrsender/com.basetis.afrsender.afrsender.MainActivity}
java.lang.RuntimeException: Performing stop of activity that is not resumed
Any suggestions about how to achieve this two way App communication?
Thank you very much.
As stated in the document
Starting from Android 3.1, the system's package manager keeps track of applications
that are in a stopped state and provides a means of controlling their launch from
background processes and other applications.
That means that till the app is not started manually by the user your app will be in force stop state and it won't receive any broadcast.
That's why your dummy app is not receiving and broadcast sent by main app.
Check here for more reference
Related
I'm trying to handle an android device shut down : When the device is shutting down, a singleton, named PostManager, sends a POST request.
To do so, i'm using a BroadcastReceiver :
public class DeviceOffReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SHUTDOWN)) {
PostManager.getInstance().onDeviceOff();
}
}
}
public class PostManager{
public void onDeviceOff() {
sendRequest();
}
}
Here is the BroadcastReceiver initialization :
IntentFilter filter = new IntentFilter(".DeviceOffReceiver");
filter.addAction(Intent.ACTION_SHUTDOWN);
mShutDownReceiver= new DeviceOffReceiver ();
app.registerReceiver(mShutDownReceiver, filter);
This code works perfectly.. but only the first time. By "first time", I mean the first time the app is run.
Has anyone ever experienced the same issue ?
EDIT : I register the intent ACTION_SCREEN_OFF. I receive it every time. It has something to do with the ACTION_SHUTDOWN intent.
My device version is 4.3.
I tried to run the app with another device (on 5.0.2) and it works every time...
So it has something to do with 4.3 (maybe ?).
Make sure you put this code into Manifest.
You can use this code to solve issue:
<receiver android:name=".DeviceOffReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
</receiver>
I am writing a Gallery like app.
I want to be notified when an image is copied to device via MTP.
I tried to register a broadcast receiver to listen for media scanner finished action, but it never got called. I tried to both register in AndroidManifest.xml or register in Java code, neither works.
<receiver android:name="com.robin.huangwei.omnigif.content.MediaScannerReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_SCANNER_FINISHED" />
<data android:scheme="file" />
</intent-filter>
</receiver>
public class MediaScannerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("-----", "Scan finished, new item: " + intent);
}
}
or using JAVA code as below
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("-----", "Scan finished, new item: " + intent);
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_FINISHED);
filter.addDataScheme("file");
registerReceiver(mReceiver, filter);
None of the above works.
Whats wrong with my code? I can see every time a new image is copied, it could show in Gallery App. It might be using content observer to watch the media store database, which I don't want to.
I just want to be notified when a new image is added into the device storage via MTP. Since it is added into media store, which must be done by media scanner, why cannot my app capture the broadcast intent? If this is not even correct, I want to know the answer I post as the title.
I am working in Android 2.1, and I want to detect when the headset is plugged in/taken out. I'm pretty new to android.
I think the way to do it is using a Broadcast receiver. I sublcassed this, and I also put the following in my AndroidManifest.xml. But do you have to register the receiver somehwere else, like in the activity? I'm aware there are lots of threads on this, but I don't really understand what they're talking about. Also, what's the difference between registering in AndroidManifest.xml versus registering dynamically in your activity?
<receiver android:enabled="true" android:name="AudioJackReceiver" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" >
</action>
</intent-filter>
</receiver>
And this was the implementation of the class (plus imports)
public class AudioJackReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.w("DEBUG", "headset state received");
}
}
I was just trying to see if it works, but nothing shows up when I unplug/plug in the headset while running the application.
EDIT: the documentation doesn't say this, but is it possible that this one won't work if registered in the manifest? I was able to get it to respond when I registered the receiver in one of my applications (or do you have to do that anyway?)
Just complementing Greg`s answer, here is the code that you need divided in two parts
Register the Service in the first Activity (here its called MainActivity.java).
Switch over the result of the ACTION_HEADSET_PLUG action in the BroadCastReceiver.
Here it goes:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private MusicIntentReceiver myReceiver;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myReceiver = new MusicIntentReceiver();
}
#Override public void onResume() {
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
registerReceiver(myReceiver, filter);
super.onResume();
}
private class MusicIntentReceiver extends BroadcastReceiver {
#Override public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
Log.d(TAG, "Headset is unplugged");
break;
case 1:
Log.d(TAG, "Headset is plugged");
break;
default:
Log.d(TAG, "I have no idea what the headset state is");
}
}
}
}
Here are two sites that may help explain it in more detail:
http://www.grokkingandroid.com/android-tutorial-broadcastreceiver/
http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html
You have to define your intent; otherwise it won't access the system function. The broadcast receiver; will alert your application of changes that you'd like to listen for.
Every receiver needs to be subclassed; it must include a onReceive(). To implement the onReceive() you'll need to create a method that will include two items: Context & Intent.
More then likely a service would be ideal; but you'll create a service and define your context through it. In the context; you'll define your intent.
An example:
context.startService
(new Intent(context, YourService.class));
Very basic example. However; your particular goal is to utilize a system-wide broadcast. You want your application to be notified of Intent.ACTION_HEADSET_PLUG.
How to subscribe through manifest:
<receiver
android:name="AudioJackReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
Or you can simply define through your application; but. Your particular request; will require user permissions if you intend to detect Bluetooth MODIFY_AUDIO_SETTINGS.
You need to enable the broadcast receiver and set the exported attribute to true:
<receiver
android:name="AudioJackReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
i created an app that has a BroadcastReceiver that catches a INSTALL_REFERRER broadcast.
When I'm installing the app with eclipse and creating a broadcast with adb I see that all work fine, the LogCat is displaying all that it should be.
But when I'm installing the app from the play store nothing is showing on the logcat.
If I understand correctly, the play store app should create a broadcast witch the app that is being installed supposed to catch, right?
Thats basicly what im doing:
public class SDK_Referrer extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals("com.android.vending.INSTALL_REFERRER"))
{
String referrer = intent.getStringExtra("referrer");
if (!(referrer == null || referrer.length() == 0))
{
// extracting the relevant data to Map
Log.d("SAMPLE", "Generating Ymid from referrel");
Map<String, String> referralmap =
createHashMapFromQueryString(referrer);
Log.d("SAMPLE", "Ymid is: " + referralmap.get("ymid"));
}
}
}
}
i only want to send someting to a server when the app is being installed.
Thanks!
You need to add the receiver to your manifest, so your app knows you have something listening for the broadcast. Something like this:
<receiver android:name="com.company.cool.SDK_Referrer" android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
I'm monitoring incoming SMSs.
My app is working perfectly with a BroadcastReceiver. However it is working from an Activity and would like to keep the BroadcastReceiver running all the time (and not just when my Activity is running).
How can I achieve this? I've looked through the lifecycle of the BroadcastReceiver but all that is mentioned in the documentation is that the lifecycle is limited to the onReceive method, not the lifecycle of keeping the BroadcastReceiver checking for incoming SMS.
How can I make this persistent?
Thanks
You need to define a receiver in manifest with action name android.intent.action.BOOT_COMPLETED.
<!-- Start the Service if applicable on boot -->
<receiver android:name="com.prac.test.ServiceStarter">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Make sure also to include the completed boot permission.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Use Service for this to make anything persist. And use receivers to receive Boot Up events to restart the service again if system boots..
Code for Starting Service on boot up. Make Service do your work of checking sms or whatever you want. You need to do your work in MyPersistingService define it your self.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ServiceStarter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent("com.prac.test.MyPersistingService");
i.setClass(context, MyPersistingService.class);
context.startService(i);
}
}
Service or Boot Completed is not mandatory
In fact, you don't need to implement a Service or register to android.intent.action.BOOT_COMPLETED
Some examples shows how to register/unregister a BroadcastReceiver when activity is created and destroyed. However, this is useful for intents that you expect only when app is opened (for internal communication between Service/Activity for example).
However, in case of a SMS, you want to listen to the intent all the time (and not only when you app is opened).
There's another way
You can create a class which extends BroadcastReceiver and register to desired intents via AndroidManifest.xml. This way, the BroadcastReceiver will be indepedent from your Activity (and will not depend from Activity's Life Cycle)
This way, your BroadcastReceiver will be notified automatically by Android as soon as an SMS arrive even if your app is closed.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest>
...
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application>
....
<receiver android:name=".MyCustomBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
MyCustomBroadcastReceiver.java
public class MyCustomBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent != null) {
String action = intent.getAction();
if(action != null) {
if(action.equals("android.provider.Telephony.SMS_RECEIVED")) {
// DO YOUR STUFF
} else if (action.equals("ANOTHER ACTION")) {
// DO ANOTHER STUFF
}
}
}
}
}
Notes
You can add others intent-filters to AndroidManifest and handle all of them in same BroadcastReceiver.
Start a Service only if you will perform a long task. You just need to display a notification or update some database, just use the code above.
Add Broadcast Reciever in manifest:
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
Create Class BootReciever.java
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
// +++ Do Operation Here +++
}
}
}
Beside #Javanator answer I would like to include a case for Android version of (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) In my case this is working for Android SDK 29 (10)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context,FloatingWindow.class));
} else {
context.startService(new Intent(context, FloatingWindow.class));
}
use this code and also mention the broadcast in Manifest also:
public class BootService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Toast.makeText(context, "Boot Completed", Toast.LENGTH_SHORT).show();
//write code here
}
}
}
I just want to mention that in case of some Chinese phone brands (e.g. MI), you need to go to Settings and give autostart permission to your app.
Otherwise the battery optimisation feature will kill your service in background and broadcast receiver will not work.
So you can redirect your user to Settings and ask them to give that permission.