I have spent the last couple of hours looking through other questions on this topic and none that I found were able to give me any answers.
What is the best way to pass a string from an activity to a broadcast receiver in the background?
Here is my main activity
public class AppActivity extends DroidGap {
SmsReceiver mSmsReceiver = new SmsReceiver();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ScrollView scroll;
scroll = new ScrollView(this);
Bundle bundle = getIntent().getExtras();
final String ownAddress = bundle.getString("variable");
registerReceiver(mSmsReceiver, new IntentFilter("MyReceiver"));
Intent intent = new Intent("MyReceiver");
intent.putExtra("passAddress", ownAddress);
sendBroadcast(intent);
Log.v("Example", "ownAddress: " + ownAddress);
}
}
Here is my broadcast receiver
public class AppReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
final String ownAddress = intent.getStringExtra("passAddress");
Toast test = Toast.makeText(context,""+ownAddress,Toast.LENGTH_LONG);
test.show();
Log.v("Example", "ownAddress: " + ownAddress);
}
}
Here is the manifest for my receiver
<service android:name=".MyService" android:enabled="true"/>
<receiver android:name="AppReceiver">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_SENT"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<receiver>
<service android:name=".MyServiceSentReceived" android:enabled="true"/>
<receiver android:name="AppReceiver">
<intent-filter android:priority="2147483645">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
When the broadcast receiver logs an event the app crashes. I need to have it run behind the scenes and pull a string from my main activity.
Can anyone help me with this or point me in the right direction?
Addition from comments and chat
Your String ownAddress will always be null unless the Intent has an String with the key passAddress in the the Bundle extras. Anytime your Receiver catches an Intent (whether from SMS_SENT, SMS_RECEIVED, or BOOT_COMPLETED) ownAddress will be null because the OS doesn't provide a String extra named passAddress. Hope that clears things up.
Original Answer
I haven't used DroidGap but this is what you want for a regular Android Activity.
Activity:
public class AppActivity extends Activity {
AppReceiver mAppReceiver = new AppReceiver();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(mAppReceiver, new IntentFilter("MyReceiver"));
String string = "Pass me.";
Intent intent = new Intent("MyReceiver");
intent.putExtra("string", string);
sendBroadcast(intent);
}
}
Receiver:
public class AppReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, intent.getStringExtra("string"), Toast.LENGTH_LONG).show();
}
}
Don't forget to unregister the receiver in onDestroy(), like this:
#Override
protected void onDestroy() {
unregisterReceiver(mAppReceiver);
super.onDestroy();
}
Related
I have App A and App B. In App A I want to send broadcast to App B.
This is the code for App A:
final Intent intent = new Intent();
intent.setAction("com.pkg.perform.Ruby");
intent.putExtra("KeyName", "code1id");
intent.setComponent(new ComponentName("com.pkg.AppB", "com.pkg.AppB.MainActivity"));
sendBroadcast(intent);
And in App B - In MainActivity, I have MyBroadCastReceiver Class.
public class MainActivity extends Activity {
private MyBroadcastReceiver MyReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Receive broadcast from External App
IntentFilter intentFilter = new IntentFilter("com.pkg.perform.Ruby");
MyReceiver = new MyBroadcastReceiver();
if(intentFilter != null)
{
registerReceiver(MyReceiver, intentFilter);
}
}
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(MainActivity.this, "Data Received from External App", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(MyReceiver != null)
unregisterReceiver(MyReceiver);
}
}
I am getting the error - Receiver is not registered.
First thing first declare the receiver in app B in the manifest file like this:
<receiver android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.pkg.perform.Ruby" />
</intent-filter>
</receiver>
when sending the broadcast add FLAG_INCLUDE_STOPPED_PACKAGES flag to the intent [src] because when you broadcast from app A to app B , app B might not be running, this flag insures that the broadcast reachs out even apps not running:
FLAG_INCLUDE_STOPPED_PACKAGES flag is 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.
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
In your case it will be like this:
final Intent intent=new Intent();
intent.setAction("com.pkg.perform.Ruby");
intent.putExtra("KeyName","code1id");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setComponent(
new ComponentName("com.pkg.AppB","com.pkg.AppB.MyBroadcastReceiver"));
sendBroadcast(intent);
In App A: Send the broadcast here.
final Intent i= new Intent();
i.putExtra("data", "Some data");
i.setAction("com.pkg.perform.Ruby");
i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
getApplicationContext().sendBroadcast(i);
In App B manifest
<receiver android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.pkg.perform.Ruby" />
</intent-filter>
</receiver>
In App B MainActivity: register the receiver oncreate(), and unregister onDestroy()
public class MainActivity extends AppCompatActivity
{
private MyBroadcastReceiver MyReceiver;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter("com.pkg.perform.Ruby");
if(intentFilter != null)
{
registerReceiver(MyReceiver, intentFilter);
}
}
#Override
protected void onDestroy()
{
super.onDestroy();
if(MyReceiver != null)
unregisterReceiver(MyReceiver);
}
}
In App B BroadcastReceiver
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String data = intent.getStringExtra("data");
Log.i("BR" ,"Data received: " + data);
}
}
There may be two cases :
Your appB is not running, hence the activity is not instantiated, and so the receiver is not registered.
Your activity is destroyed, means that you have unregistered your receiver that you registered via registerReceiver() in onCreate()
Solution :
Register your broadcast receiver in manifest.
Inside manifest of appB :
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="com.pkg.perform.Ruby" />
</intent-filter>
</receiver>
And comment out the line in appA
intent.setComponent(new ComponentName("com.pkg.AppB","com.pkg.AppB.MainActivity"));
Write the logic in MyBroadcastReceiver to display relevant data/launch new activity
MyReceiver is class not object. Create
myReceiver = new MyReceiver();
and put...........
registerReceiver(myReceiver,intentFilter);
If this helps some one and it works for me
In App A in activity or in a content provider-
Intent intent = new Intent("Updated");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setComponent (new
ComponentName "com.exam.appA",
"com.exam.appA.DbaseChanged"));
getContext().sendBroadcast(intent);
In App B in the manifest
<receiver
android:name=".DbaseChanged"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="Updated" />
</intent-filter>
</receiver>
In App B Broadcast receiver class-
public class DbaseChanged extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent
intent) {
String act = intent.getAction();
if(act != null && act.equals("Updated") )
{
Toast.makeText(context, act ,
Toast.LENGTH_SHORT).show();
}
}
}
I needed to call setPackage("package_name") to ensure explicitness when I registered the broadcast receiver in the Manifest. I was then able to receive the data even if the app was closed completely.
// sending app sends broadcast
Intent intent = new Intent(ACTION_RECOMMEND);
intent.putExtra(LISTEN_RECOMMENDATION, "Triggered - Jhene Aiko");
intent.putExtra(WATCH_RECOMMENDATION, "Goblin - Kim Go-eun");
intent.setPackage("com.example.package.receiverapp");
sendBroadcast(intent);
//receiving app manifest registers receiver
<receiver
android:name=".ManifestRegisteredBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.random.action.RECOMMEND" />
</intent-filter>
</receiver>
I didn't need to add intent.setPackage(package_name) when registering the receiver via an activity, but this also meant that I couldn't get the data if the activity was destroyed (app closed, app in background for long period)
I have an application that use parse push notification service. Here is the class that I'm using for receiving notification:
public class MessageReceiver extends ParsePushBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//...some code in here
}
And I also register this custom receiver in my manifest:
<receiver
android:name="com.package.MessageReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
Everything is fine with notification system. After a notification have received, I want to update the running activity UI accordingly (like showing an icon for new notification) but I don't have access to the activity object in onReceive method. What is the best practice to do that? I couldn't use the context object in this matter.
Thanks
I believe you can accomplish this by using a BroadcastReceiver.
You would define the receiver in the activities you want to have access to,
See snippet below.
public MyActivity extends Activity
{
//... code
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//... update ui here
}
};
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction("suitablename");
registerReceiver(receiver, filter);
super.onResume();
}
#Override
protected void onPause() {
unregisterReceiver(receiver);
super.onPause();
}
//... code
}
Then in your custom receiver send the broadcast.
public class MessageReceiver extends ParsePushBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//...some code in here
Intent intent = new Intent();
intent.setAction("suitablename");
context.sendBroadcast(intent);
}
}
Don't forget to update the manifest
<activity
android:name=".MyActivity" >
<intent-filter>
<action android:name="suitablename"></action>
</intent-filter>
</activity>
I have a Problem with my Broadcastreceiver and I have no idea what I am doing wrong.
I already read many posts #stackoverflow, but nothing helped.
I am sending a broadcast from my helperclass, the broadcastreceiver is implemented in an activity. I am putting an extra on the Intent at the helperclass before sending it, but the intent # the activity has null extras. What am I doing wrong?
This is my sourcecode:
//Helperclass
...
public static String BROADCAST_ACTION_DM = "de.je.toctohk.DISPLAYMESSAGE";
...
public void method() {
String msg = _intent.getStringExtra("message");
Intent broadcast = new Intent();
broadcast.setAction(BROADCAST_ACTION_DM);
broadcast.putExtra("msg", _chatentryid);
sendStickyBroadcast(broadcast);
}
//Activity
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String test = getIntent().getStringExtra("msg");
Toast.makeText(getApplicationContext(), intent.getExtras().getString("msg"), Toast.LENGTH_SHORT).show();
}
};
protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction(GcmIntentService.BROADCAST_ACTION_DM);
_testintent = registerReceiver(receiver, filter);
super.onResume();
}
//Manifest
<activity
android:name="de.je.toctohk.activities.ChatActivity"
android:label="#string/title_activity_push" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="de.je.toctohk.DISPLAYMESSAGE" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
What I already tried:
normal broadcast
only registering the filter in the Activity
only registering the filter in the Manifest
Sticky broadcast
context.getIntent().getExtra…
intent.getExtra…
It would be great if somebody could give me some advises.
Thanks a lot!!
I'm starting with android and I'm having some lessons to learn some android concepts. In this case, I'm practicing with the BroadCast receivers.
I have to create a BroadCast Receiver that when I boot the phone/emulator, starts an activity which shows a plain text.
I have this class:
public class MainActivity extends Activity {
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
IntentFilter mfilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
registerReceiver(receiver, mfilter);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
But i'm not getting to do what I need, it simply does nothing, so... What I'm doing wrong here?
In the manifest I just have the activity declared.
Try this...
Step1:
set the permission in AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Step2:
Add this is intent filter in receiver,
<receiver android:name=".BootReciever">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
Step3:
Now you can start your application's first activity from onReceive method of Receiver class..
public class BootReciever extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent myIntent = new Intent(context, MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
You can not register ACTION_BOOT_COMPLETED receiver dynamically(it's not a way).
ACTION_BOOT_COMPLETED receiver has to be registered statically in manifest file
ex
<receiver android:name="com.myapp.receiver.BootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
When you register a receiver in Activity or in Service it's lifetime is bound with them
You need to define your receiver inside app manifest.
For ex:
Class
class MyClass extends BroadCastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
IntentFilter mfilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
registerReceiver(receiver, mfilter);
}
}
Create your own MyReceiver class by extending BroadcastReceiver class, and register your MyReceiver in the manifest with filter ACTION_BOOT_COMPLETED.
<receiver android:name="com.test.MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I'm initiating new call from my activity. And trying to pass a boolean extra.
public class CallInitiatingActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + number));
intent.putExtra("com.demoapp.CUSTOM_CALL", true);
startActivity(intent);
}
}
I also have a BroadcastReceiver registered, which listens for outgoing calls:
<receiver android:name=".OutgoingCallListener" android:exported="true" >
<intent-filter android:priority="0" >
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Basically what I'm expecting onReceive to see my extra, but somehow it is not passed:
public class OutgoingCallListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
for (String key : extras.keySet()) {
Log.i(Constant.LOG_TAG, key + ": " + extras.get(key));
}
}
}
Output:
android.phone.extra.ALREADY_CALLED:false
android.intent.extra.PHONE_NUMBER:+370652xxxxx
com.htc.calendar.event_uri:null
android.phone.extra.ORIGINAL_URI:tel:+370652xxxxx
Your custom extra is present in the Intent that you use to start the "call" activity. But it isn't copied into the NEW_OUTGOING_CALL Intent that is broadcast as a part of the actual call mechanism. These 2 operations are distinct and only indirectly related to each other. Only the Android system itself can broadcast the NEW_OUTGOING_CALL Intent.
You can't add your own extras to this Intent. You'll need to come up with another way to do whatever it is you are trying to accomplish.