Invoking an activity from Broadcast Receiver - android

i am a beginner in android and i am developing an application where BrocastReceiver starts whenever the user makes a call... i am trying to monitor the network status inside the broadcast receiver... and i am trying to start the activity when the user hangs up the phone... but unfortunately it is giving me an error...please let me know how to do this...
My broadcast receiver starts properly when the user make a call... but i do not know how to monitor the network inside the BroadcastReceiver when the user is on call.. and invoke the activity from the BroadcastReceiver when the user hangs up the phone...
Please let me know how to achieve this... Thanks in advance.. :-)
my code...
BroadcastReceiver Code
public class MoniterNetworkStatus extends BroadcastReceiver{
private ConnectivityManager connectivityManager;
private NetworkInfo info;
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Monitering Network Status !!!", Toast.LENGTH_LONG).show();
boolean networkStatus = false;
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Intent activityIntent = new Intent(context, NetworkStatusActivity.class);
// I am monitoring the network status as long as user is on call...
while(telephonyManager.getCallState()!= TelephonyManager.CALL_STATE_IDLE){
info = connectivityManager.getActiveNetworkInfo();
if(info == null){
networkStatus = false;
}else if(info.getType() == ConnectivityManager.TYPE_MOBILE){
networkStatus = info.isConnected();
}else{
networkStatus = false;
}
}
//Putting the network details in to the activity.
activityIntent.putExtra("operatorName", telephonyManager.getNetworkOperatorName());
activityIntent.putExtra("networkStatus", networkStatus);
// starting the activity
context.startActivity(activityIntent);
abortBroadcast();
}
}
My Manifest File
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- <uses-permission android:name="android.permission.INTERNET"/> -->
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity android:name="com.abc.activity.NetworkStatusActivity"></activity>
<receiver android:name="com.abc.broadcastreceiver.MoniterNetworkStatus"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<action android:name="android.intent.action.ANSWER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
My broadcast receiver starts properly when the user make a call... but i do not know how to monitor the network when the user is on call.. and invoke the activity when the user hangs up the phone...
Please let me know how to achieve this... Thanks in advance.. :-)

You need to register another receiver to accept ACTION_PHONE_STATE_CHANGED. This may be a duplicate of Detecting outgoing call and call hangup event in android

Related

Null Extra when sending intent from BroadCast

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");

Why onReceive(Context, Intent) of BroadcastReceiver is executing twice?

I want to get call details(mobile number, call duration, date, time etc) of dialed mobile no after disconnecting call.
What I did so far:
I create a Broadcast Receiver to detect the call disconnect event. After getting call details I fetch the latest dialed no from call log and store in SQLite database.
What the problem is:
When I dial any no from device and disconnect that, onReceive() method called twice. Same record is inserted twice. I have checked it by printing Logs also.
I searched this issue on Google and got some solution like " use sendBroadcast() only once, register broadcast receiver only once etc". But I am not calling sendBroadcast()anywhere, neither I am registering it twice.
I am new to Android so please suggest what am I doing wrong?
Broadcast Receiver:
public class CallReceiver extends BroadcastReceiver {
ContentResolver contentResolver;
Context context;
boolean is_network_roaming = false;
TelephonyManager tm = null;
AppInfo appInfo = null;
ContactHelper contactHelper;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String TAG = getClass().getSimpleName();
this.context = context;
tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
appInfo = new AppInfo(context);
contactHelper = new ContactHelper(context);
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
is_network_roaming = tm.isNetworkRoaming();
/* Method for getting call details from call log */
getAllCallLogs();
}
}
Manifest File:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.callduration"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_logo"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.callduration.Splash"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#android:style/Theme.NoTitleBar"
android:windowSoftInputMode="adjustPan|adjustResize|stateHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.callduration.MainActivity" >
</activity>
<activity android:name="com.callduration.CallHistory" >
</activity>
<receiver android:name="com.callduration.receivers.CallReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
</manifest>
The sequence of state changes when dialing a call is:
CALL_STATE_OFFHOOK--->ACTION_NEW_OUTGOING_CALL-->...{call answered or not
answered}.........--> CALL_STATE_OFFHOOK-->CALL_STATE_IDLE
As per the above states, your onReceive is supposed to start twice, once when call is initiated and second when call is disconnected. To achieve what you need i.e you want to log the events of a single call session. You can use the below code,
int state=intent.getStringExtra(TelephonyManager.EXTRA_STATE)
Boolean singlecallstate=false;
switch (state) {
case TelephonyManager.ACTION_NEW_OUTGOING_CALL:
singlecallstate=true;
//any other code you want
case TelephonyManager.CALL_STATE_IDLE:
if(singlecallstate){
getAllCallLogs();
singlecallstate=false;
}

How to make the app's broadcast receiver keep listening without having a service running in the background

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.

BroadcastReceiver is not working (detect if wifi is connected)

I'm trying to use a BroadcastReceiver to detect if wifi is connected and simply display a toast when the status changes (wifi disonnect/reconnect/turn off) but it doesn't seem to be working. Any ideas?
ConnectionChangeReceiver class:
public class ConnectionChangeReceiver extends BroadcastReceiver
{
#Override
public void onReceive( Context context, Intent intent )
{
ConnectivityManager connMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final boolean isWifiConn = networkInfo.isConnected();
Log.d("debug", "Wifi connected: " + isWifiConn);
Toast toast = Toast.makeText(context, "Wifi connected: " + isWifiConn, Toast.LENGTH_LONG);
toast.show();
}
}
Manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<receiver android:name="ConnectionChangeReceiver" android:label="NetworkConnection">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
I go in the app, and disconnect wifi, reconnect, no toast. I disable wifi, no toast. re-enable it, no toast. I suspect that there's something wrong with the broadcast receiver.
Thanks in advance.
I got it working.
My problem was in the Manifest. I was putting my receiver block outside the application tag. Once I moved it inside, it worked perfectly.

Broadcast Receiver not working for voice network

I want to receive notification when Mobile network connection is lost or received. Through following code, I can receive notification for Wi-Fi (Data) connection but not for Mobile (Voice) connection.
Manifest :
<uses-permission android:name="android.permission.ACCESS_NETWORK_ST ATE"/>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name=".notifier">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE " />
</intent-filter>
</receiver>
</application>
Java :
public class notifier extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast toast = Toast.makeText(context, "Network Changed !!", Toast.LENGTH_LONG);
toast.show();
}
}
Please tell me, how can I receive notification for Mobile Network (Voice).
Pseudocode!!
PhoneStateListener myListener = new PhoneStateListener() {
#Override
public void onServiceStateChanged (ServiceState serviceState) {
// Handle different service states here.
}
};
((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE))
.listen(myListener, PhoneStateListener.LISTEN_SERVICE_STATE);
http://developer.android.com/reference/android/telephony/TelephonyManager.html#listen(android.telephony.PhoneStateListener, int)
Check the permission in the AndroidManifest.xml, first.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission>
And try this code below.
ConnectivityManager manager = (ConnectivityManager)appContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mobile = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if(mobile.isConnected()) {
//Do Sth.
}
If this is not work, check your phone's brand. If the phone's developer blocked some codes or not implement some code, it doesn't work. What is your phone?

Categories

Resources