Not able to trigger the broadcast - java

I was learning concept of broadcast receivers and I wanted to make a project with which I can demonstrate triggering specific implicit receiver class which is kind of explicit broadcast.
I made 2 apps the sender app and receiver app for demonstration :
BROADCAST SENDER's MAIN ACTIVITY :
public class MainActivity extends AppCompatActivity {
//Declaring our views
TextView senderTextView;
Button sendButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initializing views
senderTextView = findViewById(R.id.senderTextView);
sendButton = findViewById(R.id.sendButton);
//Setting onClick Listener on sendButton
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Calling Broadcast Method
Broadcast();
}
});
}
//Broadcast Method
private void Broadcast(){
//Creating private broadcast intent
Intent intent = new Intent("com.example.broadcastreceiver.PRIVATE_BROADCAST");
//Here we are going to find all the apps in our mobile that have registered for this broadcast in their manifests
//This will help us to find packages or apps registered for com.example.PRIVATE_BROADCAST action
PackageManager packageManager = getPackageManager();
//queryBroadcastReceivers of package manager will query all the receivers having intent filter for "com.example.PRIVATE_BROADCAST" action
//and store receivers info in resolveInfoList
List<ResolveInfo> resolveInfoList = packageManager.queryBroadcastReceivers(intent,0);
//Now we will iterate over this list to find our specific receiver and trigger it
//for each info in resolveInfoList
for (ResolveInfo info : resolveInfoList){
//if info's receiver class name is com.example.broadcastreceiver.CustomBroadcastReceiver (which is our receiver class in receiver app)
if(info.activityInfo.name.equals("com.example.broadcastreceiver.CustomBroadcastReceiver")){
//then use this info to get package name and receiver class name to make a componentName
ComponentName componentName = new ComponentName(info.activityInfo.packageName,info.activityInfo.name);
//now set this componentName to our intent
intent.setComponent(componentName);
}
}
//Sending our private broadcast to our android mobile
sendBroadcast(intent);
//setting textView
senderTextView.setText("Broadcast Sent!");
}
BROADCAST RECEIVER'S MANIFEST :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.broadcastreceiver">
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.BroadcastReceiver"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".CustomBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.example.broadcastreceiver.PRIVATE_BROADCAST"/>
</intent-filter>
</receiver>
</application>
</manifest>
BROADCAST RECEIVER's CustomBroadcastReceiver Class :
public class CustomBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Making a toast when broadcast is received
Toast.makeText(context, "Broadcast Receiver App : Custom Broadcast Receiver Triggered" , Toast.LENGTH_SHORT).show();
}
BroadcastReceiver's Mainactivity has nothing.
This should trigger the toast in CustomBroadcastReciever class of Broadcast Receiver App but due to some reason toast is not appearing please help.
Thanks in advance :)

Just created a demo app that works:
In app1, send the broadcast like this (obviously change package names):
public void sendBroadcast() {
Intent broadcastIntent = new Intent("com.example.testimplicitbroadcastreceiver.PRIVATE_BROADCAST");
broadcastIntent.setComponent(new ComponentName("com.example.testimplicitbroadcastreceiver",
"com.example.testimplicitbroadcastreceiver.CustomBroadcastReceiver"));
sendBroadcast(broadcastIntent);
}
In app2's manifest, register the BroadcastReceiver:
<receiver
android:name=".CustomBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.example.testimplicitbroadcastreceiver.PRIVATE_BROADCAST"/>
</intent-filter>
</receiver>
Voila, now app2 will receive your Broadcast in the CustomBroadcastReceiver.

Related

App Service won't Start after reboot by using BroadCastReceiver

I want my service to be started when android is rebooted. I used BroadcastReceiver to do so.
public class autostart extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
MyService1 mYourService = new MyService1();
MainActivity.instance_main.showToast("BroadCast Received...................");
Intent mServiceIntent = new Intent(MainActivity.instance_main, mYourService.getClass());
if (!MainActivity.instance_main.isMyServiceRunning(mYourService.getClass())) {
MainActivity.instance_main.startService(mServiceIntent);
MainActivity.instance_main.showToast("Restarted...................");
}
else {
MainActivity.instance_main.showToast("already running..................");
}
}
}
Receiver in Android Manifest
<receiver android:name=".autostart" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
Permissions defined
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
Battery optimization ignore permission also requested in OnCreate()
Intent intent=new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:"+MainActivity.instance_main.getPackageName()));
MainActivity.instance_main.startActivity(intent);
But it won't work. Service won't start on reboot. Kindly Suggest me solution.
WE need to register the receiver. Add the following code to OnCreate()
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mService=new Autostart();
registerReceiver(mService,filter);
However after reboot it wont automatically hit.

Broadcast receiver - send String between apps

I am trying to send string from app to app.
First app called "send" has only "MainActivity" class and layout:
private void sendMsg(){
final TextView msg = (TextView) findViewById(R.id.sendText);
Button snd = (Button)findViewById(R.id.sendButton);
snd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!msg.getText().toString().trim().equals("")){
Intent intent = new Intent("Updated");
intent.setAction(Intent.ACTION_SEND);
intent.putExtra("TEXT", msg.getText().toString().trim());
intent.setType("text/plain");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setComponent(new ComponentName("com.example.rec","com.example.rec.broadcastReciver"));
getApplicationContext().sendBroadcast(intent);
}else{
Toast.makeText(getApplicationContext(), "Write text that You want to broadcast!", Toast.LENGTH_LONG).show();
}
}
});
}
Second app called "rec" has two classes "broadcastReciver" and "MainActivity".
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
zoviBroadCast();
}
private void zoviBroadCast(){
broadcastReciver brcv = new broadcastReciver();
registerReceiver(brcv,
new IntentFilter("action"));
}
}
broadcastReciver:
public class broadcastReciver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent)
{
//String data = intent.getStringExtra("TEXT").trim();
if (intent != null)
{
String sIntentAction = intent.getAction();
if (sIntentAction != null && sIntentAction.equals("action"))
{
String data = intent.getStringExtra("TEXT").trim();
Toast.makeText(context, data, Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(context,"Something went wrong",Toast.LENGTH_SHORT).show();
}
}
}
}
I also added lines between tag "receiver" in "AndroidManifest.xml":
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rec">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".broadcastReciver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="action" />
</intent-filter>
</receiver>
</application>
</manifest>
What application should do is when I type something in first application and send it another over button it should "broadcast" (show) toast at second app.
My second application is not showing any data when run.
Nowadays it is essential to specify an action in intent filter of your broadcast receiver.
<receiver android:name="MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_ACTION">
</action>
</intent-filter>
</receiver>
When sending the broadcast, you need to set exactly the same action to the intent you send.
Intent i = new Intent();
i.setAction("android.intent.action.MY_ACTION");
context.sendBroadcast(i);
Notation of action name may be not very important to get your code working, but I recommend to give names related to the package of your sending app.
For example: "com.username.example.myApplication.ACTION_EXAMPLE"

Android - Unable to receive local broadcast in my activity from service

I have my main activity that start a service (Location service) and I want that service to broadcast the new location each time a new location is found.
Thanks to the log I know the service is working and I have new locations every seconds or so, but I never get the broadcast.
MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = "mainActivity";
private CMBroadcastReceiver mMessageReceiver = new CMBroadcastReceiver();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// Start Service
startService(new Intent(this, LocationService.class));
super.onCreate(savedInstanceState);
}
#Override
public void onResume()
{
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, new IntentFilter(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE));
super.onResume();
}
#Override
public void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
}
CMBroadcastReceiver.java
public class CMBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "CMBroadcastReceiver";
public static final String RECEIVE_LOCATION_UPDATE = "LOCATION_UPDATES";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received broadcast");
String action = intent.getAction();
if (action.equals(RECEIVE_LOCATION_UPDATE))
{
Log.i(TAG, "Received location update from service!");
}
}
}
LocationService.java
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.i(TAG, "onLocationChanged " + location);
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Log.i(TAG, "Broadcast sent");
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyclemapapp.gpstracker">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar">
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".LocationService" android:process=":location_service" />
</application>
I the log I can see that "Broadcast Sent" But I never get the "Broadcast Received"
Any help will would be greatly appreciated.
EDIT:
Edited how the intent was created in the location service as Shaishav suggested.
Still doesn't work.
LocalBroadcastManager does not work across processes. Your Service is running in a separate process.
You can either run your Service in the same process as the Activity - by removing the process attribute from the <service> element - or use some sort of IPC instead - e.g., by sending and receiving the broadcasts on a Context instead of LocalBroadcastManager.
In your LocationService, send local broadcast using:
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
<service android:name=".LocationService" android:process=":location_service" />
Your service is in a separate process from the activity. LocalBroadcastManager is only for use in one process. Either remove android:process from the <service>, or use some IPC mechanism (e.g., system broadcasts, properly secured).

Already initialised object is set to null in BroadcastListener Method: onReceive

My Class NetworkListener should check, if Internet Connection is available or not. Then, It should show a Snackbar with the InternetState. For this, I'm using an interface.
My whole code:
[MainActivity.java]:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle(R.string.Inbox);
Initialize_NavigationDrawer();
Initialize_Objects();
//1. Here, I initialise my NetworkListener and register my Receiver
NetworkListener mNetworkListener = new NetworkListener();
mNetworkListener.registerReceiver(this);
}
#Override
public void ToggleSnackbar(boolean ShowHide) {
if (ShowHide) snbNoInternet.show();
else snbNoInternet.dismiss();
}
[NetworkListener.java]:
public class NetworkListener extends BroadcastReceiver {
private SnackbarInterface snbInterface;
public NetworkListener() {}
#Override
public void onReceive(Context context, Intent intent) {
//4. After toggling the Network-Connection, a NullReferenceException occurs
//5. System.out.println(snbInterface) shows: null
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni == null || !ni.isConnected()) {
snbInterface.ToggleSnackbar(true);
}
else if (ni != null && ni.isConnected()) {
snbInterface.ToggleSnackbar(false);
}
}
public void registerReceiver(SnackbarInterface receiver) {
snbInterface = receiver; //2. Is called from onCreate
//3. System.out.println(snbInterface) shows: at.guger.email.activities.MainActivity#27472a5e
}
public interface SnackbarInterface {
public void ToggleSnackbar(boolean ShowHide);
}
}
[AndroidManifest.xml]:
<activity
android:name=".activities.MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.WriteActivity" />
<activity
android:name=".activities.ReadActivity" />
<receiver
android:name=".NetworkListener">
<intent-filter>
<action
android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
And the permissions:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
The code is called like the numbers are ordered!
I really can't explain, why snbInterface is set to null!
I hope you can help me!
You registered the BroadcastReceiver using the receiver element in the AndroidManifest. Android system creates the BroadcastReceiver instance and calls the onReceive method with the appropriate parameters.
If you want to use a BroadcastReceiver to manipulate UI of your application (like show/hide Snackbar ), you will have to register the receiver within your activity using the registerReceiver(BroadcastReceiver receiver,IntentFilter intentFilter) in the onCreate method and unRegister in the onDestroy method of your activity.
Remove the receiver element from the AndroidManifest.xml file and create the BroadcastReceiver through code.
This question here has a clear explanation on how BroadcastReceivers can be created and registered :
Broadcast Receiver class and registerReceiver method
In the onReceive method of the BroadcastReceiver, call the toggleSnackbar method in your Activity to toggle the Snackbar.
There is an other method for achieving what you want. It is discussed here:
Inform Activity from a BroadcastReceiver ONLY if it is in the foreground
Read more on BroadcastReceivers here
You can write the Receiver as a separate class. Instantiate the Receiver and make a call to registerReceiver with the first parameter as the Receiver and the second parameter as the IntentFilter.

My android homescreen widget appears, but is not updating

I already found others questions similar to mine, but could not find the solution. I have a custom widget with simple TextView and also a configuration Activity. Problem is:
When widget is added to homescreen, configurations activity appears, but onUpdate() method of AppWidgetProvider runs immediately, as soon as configuration activity is created. It should run after configuration activity is closed by pressing OK button.
Even if onUpdate() method run on configuration activity start (according to Toast in the method,showing proper data for textview), the TextView remains still not updated.
Even if android:updatePeriodMillis is set to 1000ms, onUpdate method run only once - when configuration activity starts.
When I add the widget to my homescreen and then restart phone, the widget's TextView is finally updated with proper time, but only once.
Many users have been reporting similar problems on recent android versions, like 4.4. Is there any final solution for this bad behavior?
Here are my files - Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="incredible.riskofrain.app">
<application android:allowBackup="true"
android:label="#string/app_name"
android:icon="#drawable/main_icon">
<receiver android:name=".RORAppWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/ror_appwidget_info" />
</receiver>
<activity android:name=".RORAppWidgetConfigure">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
<activity android:name="incredible.riskofrain.app.MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
appwidget_info:
android:minWidth="200dp"
android:minHeight="80dp"
android:updatePeriodMillis="1000"
android:initialLayout="#layout/ror_appwidget"
android:configure="incredible.riskofrain.app.RORAppWidgetConfigure"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen" >
AppWidgetProvider:
public class RORAppWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
Calendar c = Calendar.getInstance();
String time = "" + c.get(Calendar.MINUTE)+ ":" + c.get(Calendar.SECOND);
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.ror_appwidget);
views.setTextViewText(R.id.textview, time);
appWidgetManager.updateAppWidget(appWidgetId, views);
Toast.makeText(context, "onUpdate " + time + " " + appWidgetId, Toast.LENGTH_LONG).show();
}
}}
AppWidgetConfigure:
public class RORAppWidgetConfigure extends Activity {
int appWidgetId; Button button; AppWidgetManager appWidgetManager;
RemoteViews views;
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.ror_configure);
button = (Button) findViewById(R.id.button);
appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
Bundle extras = getIntent().getExtras();
if (extras != null) {
appWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
views = new RemoteViews(getPackageName(), R.layout.ror_appwidget);
appWidgetManager.updateAppWidget(appWidgetId, views);
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_OK, resultValue);
Toast.makeText(getApplication().getApplicationContext(), "Configure, ID: - " + appWidgetId+"", Toast.LENGTH_LONG).show();
finish();
}
});
super.onCreate(savedInstanceState);
}}
you can update Widget using broasdcast Receiver ..
check this link:
Reference Link
<!-- Broadcast Receiver that will process AppWidget updates -->
<receiver android:name=".WordWidget" android:label="#string/widget_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="#xml/widget_word" />
</receiver>
i hope its useful to you..
I found this in documentation, probably this is the problem:
public int updatePeriodMillis
Added in API level 3
How often, in milliseconds, that this AppWidget wants to be updated. The AppWidget manager may place a limit on how often a AppWidget is updated.
This field corresponds to the android:updatePeriodMillis attribute in the AppWidget meta-data file.
Note: Updates requested with updatePeriodMillis will not be delivered more than once every 30 minutes.
I also found that there is a huge bug in android framework making configuration activity useless: https://code.google.com/p/android/issues/detail?id=3696

Categories