I have a receiver in my manifest.
<receiver
android:name="com.deviceinventory.StartAppAtBootReceiver"
android:enabled="true"
android:exported="false"
android:label="StartMyServiceAtBootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
And my com.deviceinventory.StartAppAtBootReceiver onReceive() is
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent startUpIntent = new Intent(context, StartUpActivity.class);
startUpIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startUpIntent);
}
Since StartUpActivity uses internet, So I want to start this activity after boot when internet connection is available.
Currently It starts sometime before internet connection has been established.
I don't have idea how to modify the receiver in manifest and BroadCastReceiver
For that you need to add one more Receiver to check Internet Connection is Enable/Disable, When its enable you can start your bootReceiver or Any Activity you want to run.
public class NetworkInfoReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
try {
/***
* Here we need to check its running perfectly means this receiver
* call when net is off/on. You should have to check
* */
final ConnectivityManager conMngr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
// Check if we are connected to an active data network.
final NetworkInfo activeNetwork = conMngr.getActiveNetworkInfo();
final boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
if (isConnected) {
/**
* Start service/receiver/activity here.
* */
} else {
/**
* Stop service/receiver/activity here.
* */
}
} catch (final Exception e) {
}
}
}
And you add this receiver into AndroidManifest.xml file.
<receiver
android:name=".NetworkInfoReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
You can try editing you intent filter. Now you recierver will respond when the device is booted completly. Change that to respond it when the connectivity changes...
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
Hope this peice of code will help you.
#Hemant you need to check in onReceive that both the conditions met to start a service.
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if(intent.equals(Intent.ACTION_BOOT_COMPLETE) && wifiManager.isWifiEnabled()){
//start your service
}
}
Related
I have a broadcast receiver that detects wether the application is connected to Internet or not and sends an intent with a string extra. But I am getting a null Extra :
This is the BroadcastReceiver
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable() || mobile.isAvailable()) {
context.sendBroadcast(new Intent().putExtra("cnx","yes"));
}
else{
context.sendBroadcast(new Intent().putExtra("cnx","no"));
}
}
}
and this my Activity code :
networkChangeReceiver=new NetworkChangeReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String val=intent.getStringExtra("cnx");
Snackbar snackbar = Snackbar
.make(layoutLauncher, "Pas de connexion Internet!"+val, Snackbar.LENGTH_LONG);
snackbar.show();
/* if (val.equals("internet")){
isNetworkAvailable(false);
}
else{
isNetworkAvailable(true);
}*/
}
};
and this is the register code
private void registerNetworkBroadcast() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
registerReceiver(networkChangeReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
registerReceiver(networkChangeReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
}
This is part of the manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tn.formation.mdsoft.bulletinimmobilier">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application.....
<activity android:name=".ui.activities.LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".services.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".services.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<receiver android:name=".tools.NetworkChangeReceiver" >
</receiver>
The intent is meant for LauncherActivity.
Edit
The scenario was faulted anyway so I neglected its implementation but in such case, better verify the the keys.
But I am getting a null Extra
Android does not have an "internet" or "cnx" extra on that Intent. And, you are creating an endless loop.
The system sends out a CONNECTIVITY_ACTION broadcast.
You have two receivers registered for that broadcast, and both receive the broadcast, with no "internet" or "cnx" extra.
One receiver adds the "cnx" extra to the CONNECTIVITY_ACTION Intent and sends the broadcast.
You have two receivers registered for that broadcast, and both receive the broadcast, with the "cnx" extra.
One receiver re-adds the "cnx" extra to the CONNECTIVITY_ACTION Intent and sends the broadcast.
You have two receivers registered for that broadcast, and both receive the broadcast, with the "cnx" extra.
One receiver re-adds the "cnx" extra to the CONNECTIVITY_ACTION Intent and sends the broadcast.
Lather, rinse, repeat
First, do not use system broadcasts for communicating within a single process of an app. Use LocalBroadcastManager.
Second, do not send a broadcast with a system Intent action. At best, you screw up lots of other apps on the device. At worst, you crash, because the system prevents you from sending that broadcast.
And, as Burhanuddin pointed out, you are not using the same key for your extra.
Your intent key is different
Here you key is "cnx"
if (wifi.isAvailable() || mobile.isAvailable()) {
context.sendBroadcast(intent.putExtra("cnx","yes"));
}
else{
context.sendBroadcast(intent.putExtra("cnx","no"));
}
Your are retriving with "internet" key here
String val=intent.getStringExtra("internet");
Change it to:
String val=intent.getStringExtra("cnx");
public class InternetChecker extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
if (cm == null)
return;
if (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected()) {
//execute my async activity
}else{
//store the values in temp file
}
}
}
This is what in my manifest file
<receiver android:name="com.company.InternetChecker" android:exported="false">
<intent-filter>
<action android:name="android.net.wifi.STATE_CHANGE" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Problem is it is only getting detected when the INTERNET is made ON from OFF state
When the data connection goes and comes back it don't react to it.
For instance WiFi connection is unstable and then again stable the background service doesn't work accordingly
Physically when the internet/WiFi is turned ON from OFF state this background service
I hope i am clear
I am trying to allow user to post comment when he is offline such that whenever wifi/internet is turned on his comment will be posted.Fot that I am using BroadCastReceiver.But the issue i am having is that it is never going inside if (intent.getAction().equals("commentpost")) if i try switching on wifi after clicking on postcomment.However it does go inside if (wifi.isAvailable() || mobile.isAvailable()) whenever i switch on wifi.I failed to understand where i am going wrong.My log shows "Network Available" but never shows "posting comment".
commentpost.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
Intent intent = new Intent();
intent.setAction("commentpost");
mContext.sendBroadcast(intent);
}
}
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable() || mobile.isAvailable())
{
Log.e("Network Available", "Flag No 1");
if (intent.getAction().equals("commentpost")) {
Log.e("posting comment", "Flag No 2");
postComment();
}
}
}
}
Manifest
<receiver android:name="xyz.NetworkChangeReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"></action>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
</intent-filter>
</receiver>
You need to add your custom action to the intent-filter of your BroadcastReceiver. Only then will that Intent trigger your BroadcastReceiver.
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"></action>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="commentpost"/>
</intent-filter>
I'm trying to make an android application which listens to wifi change broadcast and do some action. But the problem is that it is not working when the process is killed. I found this question which says that it won't work without an activity
How to create BroadcastReceiver without Activity/Service?
So that is not an alternative. Hence I created an activity which is empty. I don't want to create a service which keeps running in the background. How can I make my application keep listening even when it is killed. I have registered the broadcast in the manifest.
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.background.service.BroadCastReceiver">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
This is my class
public class BroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//do some action
}
}
Looks like you have it correct defining in the manifest with one exception. The broadcast receiver will trigger an ANR if it doesn't complete in 10 secs. http://developer.android.com/training/articles/perf-anr.html
in your broadcast receiver simply start a service.
public class ReceiverUpload extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, ServiceUploader.class));
}
}
Then in your service start an asynctask because you don't want to be on the UI thread for example you start the same service from an activity in your app.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// start asynctask to get off this thread
new MyBackGround().execute(startId);
return Service.START_REDELIVER_INTENT;
}
First thing to do in the asynctask is check for wifi
Below is excerpt from a function I call to check network if it returns false the asynctask just finishes if it's true it does network stuff which hey has to be in the background anyways so asynctask makes even more sense.
// check for network connection
ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connMgr == null) {
return false;
}
// check ok to process
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo == null || !networkInfo.isConnected()) {
return false;
}
boolean isWifi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
if (!isWifi) {
return false;
}
return true;
Note in this example the startId passed to the asynctask is used to cancel OS redelivering the intent.
#Override
public void onPostExecute(Integer startId) {
if (startId != null) {
stopSelfResult(startId);
}
}
You already doing right with the Broadcast Receiver and declaring it the Manifest. That's all you need to do. No services running in the background are needed.
Just make sure you install and run the app at least once otherwise the broadcast receives won't be registered
The best that worked for me:
AndroidManifest
<receiver android:name="com.AEDesign.communication.WifiReceiver" >
<intent-filter android:priority="100">
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
BroadcastReceiver class
public class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if(info != null) {
if(info.isConnected()) {
// Do your work.
// e.g. To check the Network Name or other info:
WifiManager wifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
}
}
}
}
Permissions
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
best solution is to make a broadcast receiver , it will work
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable() || mobile.isAvailable()) {
// Enjoy coding here
Log.d("Netowk Available ", "Flag No 1");
}
}}
in manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcastreceiverforinternetconnection"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
</application>
Normally, if app is killed and broadcast comes your app process will be started by system for you. There is absolutely no need to keep something alive or do any additional manipulations (otherwise why would you need BroadcastReceiver if you can just use Service?)
Updated answer 05/2022
The docs on Broadcasts and Broadcast limitations inform that from Android 7 (Android 8 made it even more stringent)
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 means, for most use cases manifest-declared Broadcast won't work anymore and must be replaced with scheduled jobs or services. Be aware, the latter suffers from being killed by the OS for battery optimization.
My question is, Is there any way to find out the network disconnected time? when will it goes off or when will goes On mode?
Thanks in advance For any suggestion and help.
You can create a BroadcastReceiver that listens to Intents with android.net.conn.CONNECTIVITY_CHANGE action.
public class ConnectivityListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// There is action occured with network.
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(
Context.CONNECTIVITY_SERVICE);
// query connectivity manager for network state.
}
}
Dont forget to declare this receiver in the AndroidManifest.xml:
<receiver android:name=".ConnectionChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>