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;
}
Related
I am working on an app that will use a BroadcastReceiver to pick up certain SMS messages that meet certain criteria. It's a long way short of finished, mainly because it seems that the BroadcastReceiver isn't working. I've tried to use a toast to check if it's working but I get no result. So either:
The BroadcastReceiver is not working
My method of testing is wrong
Or both
The AndroidManifest.xml file is
<?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.alert6">
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<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/Theme.Alert6">
<activity
android:name=".SendResponseActivity"
android:parentActivityName=".ReceiveAlertActivity">
</activity>
<activity
android:name=".ReceiveAlertActivity"
android:parentActivityName=".MainActivity">
</activity>
<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=".SmsBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="999" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
And this is the SmsBroadcastReceiver java file
package com.example.alert6;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.provider.Telephony;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SmsBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"SMS Is Being Received",Toast.LENGTH_LONG).show();
if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
String smsSender = "";
String smsBody = "";
for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
smsSender = smsMessage.getOriginatingAddress();
smsBody = smsMessage.getMessageBody();
}
if (smsSender.equals("+420775367297")) {
if (smsBody.contains("Test")) {
// I haven't done this bit yet
}
}
}
}
}
When I send a SMS to the test device I would expect a toast message saying "SMS Is Being Received". Instead the app disappears from the screen and my default SMS app appears instead. What am I doing wrong?
Since Android API 23 you need set permission not only in manifest class, but also set permisson manually. You should set it in app's settings, or you should make permission reqeust from your code. This is what you need add in your main activity's file:
// constant for request code
private final int MY_PERMISSIONS_REQUEST_SMS_RECEIVE = 10; // any number which you want
//function for permission request
#RequiresApi(api = Build.VERSION_CODES.M)
public void checkPermission() {
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED)) {
requestPermissions(new String[]{Manifest.permission.RECEIVE_SMS}, MY_PERMISSIONS_REQUEST_SMS_RECEIVE);
}
}
Also you need call this function somewhere. For example you can make it in onCreate().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkPermission();
}
//do something else
}
After a huge amount of fiddling and testing, I came to the conclusion that the broadcast receiver is not working. Probably due to Android's limitations on "dangerous" permissions. I don't think this thread has any life left in it, but I will continue to try to persuade my Android app to work with the necessary permissions.
I want to implement getting incoming call events in background and foreground. So I've created BroadcastReceiver for that purpose, but onReceive() method doesn't fired after I got/getting/finished incoming call.
I've tryed tons of tutorial, but nothing helped me:(
Please help.
MANIFEST
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="yakiv.bondar.dev.incomeoutcomecalltest">
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<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">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".IncomingCall"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
Broadcast receiver
public class IncomingCall extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("tag", "AAAAAAAAAAAAAAAAAAAAAA");
MyPhoneStateListener phoneListener=new MyPhoneStateListener();
TelephonyManager telephony = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
public class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state,String incomingNumber){
switch(state){
case TelephonyManager.CALL_STATE_IDLE:
Log.d("tag", "IDLE");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("tag", "OFFHOOK");
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("tag", "RINGING");
break;
}
}
}
}
Main Activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
You have missed calling registerReciever(intent,intentFilter) in your Activity. Register your activity in onResume() and call unregisterReciever(intent) in your onPause() method.
NOTE:
Also check if you have given appropriate permissions in your manifest and also note that even if you have declared your required permissions you have to handle certain permissions in runtime in Android 6.0 and above. Check here for handling permissions at runtime for Marshmallow and above.
In MainActivity:
IncomingCall mBroadcastReceiver = new IncomingCall();
In onResume:
IntentFilter filter = new IntentFilter();
this.registerReceiver(mBroadcastReceiver , filter);
In onPause:
this.unregisterReceiver(mBroadcastReceiver );
1) Make sure your app has the permissions to READ_PHONE_STATE
2) you do not need to registerReceiver( BroadcastReceiver, IntentFilter) since you have it in your Manifest
3)MAke sure the notification are turned on for your App (Check Settings--> Application Manager --> your app --> Notifications)
4) I would try testing without "break" in the switch statements
5) try with Toast instead of Log. Toast.makeText( Context, String , Toast.LENGTH_SHORT).show();
In my i have a receiver to predict incoming calls,Once i have the call i need bring my app to front of screen(Over call accept and reject scree), the code for receiver is shown below,
public class IncomingCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
Log.i("IncomingCallReceiver",bundle.toString());
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
Log.i("IncomingCallReceiver","State: "+ state);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))
{
String phonenumber = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.i("IncomingCallReceiver","Incomng Number: " + phonenumber);
String info = "Detect Calls sample application\nIncoming number: " + phonenumber;
Intent intent2open = new Intent(context, com.varma.samples.detectcalls.ui.MainActivity.class);
intent2open.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent2open.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
String name = "KEY";
String value = "String you want to pass";
intent2open.putExtra(name, value);
context.startActivity(intent2open);
Toast.makeText(context, info, Toast.LENGTH_LONG).show();
}
}
}
in my manifest i added following parameters,
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name="com.varma.samples.detectcalls.ui.MainActivity"
android:label="#string/app_name" android:launchMode="singleTop" android:taskAffinity="#android:string/no">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.varma.samples.detectcalls.receivers.OutgoingCallReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
<receiver android:name="com.varma.samples.detectcalls.receivers.IncomingCallReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="3" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
But when i launch the activity the receiver is started to listen incoming calls,then i close all instance of app in Settings, when call is coming for first time, my app is bring front over answer & reject screen.
Then i push back button to reject my call. Then when i make a call again the activity was not bring in front of my dialing screen. I don`t know where is the problem.
I declared a BroadcsastReceiver(Action_headset_plug) in AndroidManifest.xml and defined a BroadcastHandler.class implement BroadcsastReceiver . I run the apk on the device and the receiver doesn't fire. However , it work correctly when I use registerReceiver() in the Activity. Do I miss something in the AndroidManifest.xml?
This is the AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="irdc.Earphone_test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="9" />
<uses-permission android:name="android.permission.ACTION_HEADSET_PLUG"></uses-permission>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:enabled="true" android:name="BroadcastHandler">
<intent-filter>
<action android:name="android.intent.ACTION_HEADSET_PLUG"></action>
</intent-filter>
</receiver>
<activity android:name=".Earphone_testActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
This is the receiver code
public class BroadcastHandler extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)){
String mes;
int state = intent.getIntExtra("state", 4);
if(state == 0){
mes ="out";
}else if(state == 1){
mes ="in";
}else {
mes ="others";
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Headset broadcast");
builder.setMessage(mes);
builder.setPositiveButton("Okey-dokey", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
}
}
For listening to headset changes, the broadcast receiver cannot be declared in the manifest, it must be dynamically registered. Not all receivers work when declared in the manifest and this is an example where you need to register it programmatically.
You can call this for example in an Activity's onResume method or in a Service's onCreate method:
headsetReceiver = new BroadcastHandler();
registerReceiver(headsetReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
Then in the Activity's onPause method or in the Service's onDestroy method you need to unregister the receiver:
unregisterReceiver(headsetReceiver);
The name is wrong in the manifest entry. Use the full package name, or start it with a period if you want it implicitly appended to the app's package name:
<receiver android:enabled="true" android:name=".BroadcastHandler">
Most examples of receivers do not start an AlertDialog but Toast a message or create a Notification in Status bar. I am sure that you cannot start an Activity because the "content" object stops existing but not if you can built an AlertDialog. (documentation of Broadcasts)
So you can try at your receiver a Toast message to make sure that it works.
Example with Notification: http://www.anddev.org/recognize-react_on_incoming_sms-t295.html
I would like to retrieve the incoming call's phonenumber and do something with it like the do
in http://blog.whitepages.com/2009/02/27/caller-id-by-whitepages-a-new-android-app-that-puts-telemarketers-on-alert/
Could you please help me because I can't find any information about this.
Where do i start and how do i get hold of the phonenumber?
Ok so currently my code looks like below. When I place the call the CustomBroadcastReceiver catches it and the log message is printed out. I can retrieve the telephone number from the bundle. But! I can't get hte CustomPhoneStateListener to work. As you can see I have registered my customPhoneState listener to the receiver but the log message never get's printed out from the CustomPhoneStateListener class. What am I my missing here?
Is my thinking correct?
<receiver android:name=".CustomBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="5" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
public class CustomPhoneStateListener extends PhoneStateListener {
private static final String TAG = "CustomPhoneStateListener";
public void onCallStateChange(int state, String incomingNumber){
Log.v(TAG, "WE ARE INSIDE!!!!!!!!!!!");
Log.v(TAG, incomingNumber);
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.d(TAG, "RINGING");
break;
}
}
public class CustomBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "CustomBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "WE ARE INSIDE!!!!!!!!!!!");
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
Bundle bundle = intent.getExtras();
String phoneNr= bundle.getString("incoming_number");
Log.v(TAG, "phoneNr: "+phoneNr);
}
Use PhoneStateListener. It has an onCallStateChanged handler; one of the supplied arguments you'll get is a String containing the incoming phone number.
Your overridden method in CustomPhoneStateListener should be called onCallStateChanged() (and not onCallStateChange()).
This would have been spotted by the Java compiler if you would have had the #Override annotation, like you have for onReceive().
The above answers are out-od-dated now. There are valid for Android 7 and lower.
For android 9 and higher you have to add another permission in the Androidmanifest.xml with the permission
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
without the phone number will be null. For Android 8 I am not sure.
PhoneStateReciever.java
package com.incomingcalls;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
public class PhoneStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.e("Incoming Number", "Number is ," + incomingNumber);
Log.e("State", "State is ," + state);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
Toast.makeText(context,"Incoming Call State",Toast.LENGTH_SHORT).show();
Toast.makeText(context,"Ringing State Number is -"+incomingNumber,Toast.LENGTH_SHORT).show();
}
if ((state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))){
Toast.makeText(context,"Call Received State",Toast.LENGTH_SHORT).show();
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(context,"Call Idle State",Toast.LENGTH_SHORT).show();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
AnroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.incomingcalls">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<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"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".PhoneStateReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
</manifest>