I'm making an Android app with incoming calls.
Is there any way in my app, to know if user rejected any incoming call before answering it?
First, you have to add a permission in manifest file.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Then you have to register a broadcast receiver in the manifest file.
<receiver android:name=".YourReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Then write in your broadcast receiver's onReceive method:
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
//If the phone is **Ringing**
}else if(state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK){
//If the call is **Received**
}else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
//If the call is **Dropped** or **Rejected**
}
}
If the state changes from TelephonyManager.EXTRA_STATE_RINGING to TelephonyManager.EXTRA_STATE_IDLE, then it will be a missed call.
Like this you have to check the conditions.
Please put a log in those conditions. Then see the logs. I think you will get your answer.
It's been a while since you asked, but I think it might be useful for future reference for others.
If you extract data from Android's calllog (e.g to XML or in your case to a variable in your app) you have two fields of interest:
1) numbertype e.g 1 for Incoming, 2 for Outgoing, 3 for missed
2) duration (in seconds)
Rejected number is (as you correctly mentioned) treated as numbertype=1. However if you combine numbertype=1 AND duration=0 (since any call answered will have duration>0) then this hopefully solves your problem.
I'm using Android 6, not sure if the types changed since then, but with me the above method works 99.9% of the time. Never managed to hang up the phone in less than a second :)
Related
I tried to wrap my head around Android BroadcastReceiver but with no success. I'm trying to implement something simple:
Listen to an incoming SMS
Check if the number is saved
If it is saved do something
So far I registered / created the BroadcastReceiver and I'm able to catch the incoming messages. I did this in the following way:
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
//do things
}
}
}
I registered the receiver in the Manifest file in the following way:
<receiver
android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS"
android:exported="true">
<intent-filter android:priority="2147483647" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Everything fine until now.
But, and here is the big BUT: I also created a class called 'UserManager' with a few basic tasks, for example: adding a new user, deleting a user, checking if the user exists, etc.
I store the users in a HashMap (phoneNumber, Name).
My questions are:
How can I pass an Object to my BroadcastReceiver? ( I want to be able to access the HashMap from the "UserManager" class)
I found a lot of topics regarding BroadcastReceivers. Some of them said that there are a couple ways of declaring a broadcast receiver. For example you could do it the way I did ( declaring it in Manifest), or you could do something more uhm... context based? Like declaring it BroadcastReceiver br = new MyBroadcastReceiver() and registering intentFilters to it. What is the difference? Which one should I use?
Is there something called "good practice"? What should I pay attention to? Do you know any material which explains clearly the different ways of using a broadcastReceiver?
You can use dependency injection. Or just hold reference to a class in you Application, that can be accessed by getApplicationContext
Difference is - for receivers declared in manifest you can receiver messages even if you app is in destroyed state. If you broadcast receiver is created manually, well, you must create it before message will be delivered. Also Android forces some restriction on receivers declared in manifest.
I'm doing an application using ACTION_MEDIA_BUTTON handler, but it appears it is always intercepted by MX Player or Apollo and I get no Intent
I've tried both 1000 and 2147483647 priority set in tag and directly after constructor with setPriority
Applications works when no MX Player or Apollo is present
I've also tried using Headset Interceptor app from google play, I tried to deny events to MX Player with Autostarts application - nothing helps
in onCreate:
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
filter.addAction(Intent.ACTION_HEADSET_PLUG);
filter.setPriority(1000);
registerReceiver(receiver, filter);
in Receiver
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
// NEVER REACHES HERE WHEN MX PLAYER PRESENT. WORKS IF NOT
in manifest
<receiver
android:name="BCreceiver"
android:enabled="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
Refer to the line "The value must be greater than -1000 and less than 1000." from below link, highest priority is 999 not 1000.
http://developer.android.com/guide/topics/manifest/intent-filter-element.html
Even though this a little old question, I am adding my findings, so that it will help new visitors.
To receive Intent.ACTION_MEDIA_BUTTON broadcast registering intent from code is not required. Documentation says intent has to be registered in the manifest. Could not get it working from registering from code.
Use registerMediaButtonEventReceiver
Setting priority in manifest android:priority="<int value>" works. I used 2147483647 and was even able to override the stock player. I read winamp is using the highest priority.
Hope this helps.
To capture headset button one should register receiver in media too in onCreate in Activity
AudioManager manager = (AudioManager) getSystemService(AUDIO_SERVICE);
manager.registerMediaButtonEventReceiver(new ComponentName(getPackageName(), BCreceiver.class.getName()));
First of all, you shouldn't register the receiver in code if it's already mentioned in the manifest. Then, the name of the receiver is invalid, it should either be a full class name, or the shorthand, which will be appended to the application package name. In case if BCreceiver is in the main package, the attribute value should be ".BCreceiver". Last mention is that you shouldn't really change the priority, there is no such thing as intercepting a broadcast in Android (as far as I know), so all BroadcastReceivers subscribed to an action will receive the broadcast when it's fired. Try these fixes and update your question.
this is my receiver registered in my menifest file
<receiver android:name=".Network_change" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
now what I am trying to do is whenever the network type is change like GSM to UMTS or EDGE to UMTS etc I want to get this type what I already did is I save network type when my app is started in previous_network_type variable and in receiver
current_network_type=telephony.getNetworkType();
after doing my work
previous_network_type=current_network_type;
and these variables are static in a service and that service is running so the Problem is M getting 0 in both variables some time in one which is incorrect any help? coz 0 is unknown
For what you say I understand you're not taking into account that every time the receiver is triggered it creates a new instance, which is destroyed after its work. Even with static variables you don't have persistent values.
One solution that worked for me is to use SharedPreferences. Be aware that on API11+ you should use the flag MODE_MULTI_PROCESS, something like this:
if (Build.VERSION.SDK_INT>=11)
mySettings=context.getSharedPreferences("MyPrefs",Context.MODE_MULTI_PROCESS);
else
mySettings=context.getSharedPreferences("MyPrefs",0);
int netType = mySettings.getBoolean("netType",0);
Hope it helps...
I am trying to register a BroadcastReceiver programmatically to receive android.intent.action.MEDIA_MOUNTED. However, the onReceive() method never gets triggered. The same BroadcastReceiver class I created works fine if I register is statically in the app's manifest file.
Why is this the case? Is there a way to troubleshoot this? I need to register dynamically because my BroadcastReceiver class contains members that I want a service to query later on. If I catch this Intent statically then I have no easy way of querying these members because I believe the instance of BroadcastReceiver gets deleted as soon as onReceive() finishes. Is this correct? I am pretty sure this is the case considering the Android documentation has the following to say about this:
If this BroadcastReceiver was launched through a tag, then the object is no longer alive after returning from this function.
UPDATE 1:
Here is my dynamic registration code:
if (externalStorageListener == null)
{
Log.d(TAG, "creating externalStorageListener...");
IntentFilter filterExternalStorage = new IntentFilter();
filterExternalStorage.addAction(Intent.ACTION_MEDIA_MOUNTED);
filterExternalStorage.addDataScheme("file");
filterExternalStorage.setPriority(Integer.MAX_VALUE);
externalStorageListener = new ExternalStorageBroadcastReceiver();
registerReceiver(externalStorageListener, filterExternalStorage);
}
Here is the intent filter in my manifest that actually works:
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<data android:scheme="file"/>
</intent-filter>
Occasionally, to receive android.intent.action.MEDIA_MOUNTED with dynamically created BroadcastReceiver one is to have android.permission.MOUNT_UNMOUNT_FILESYSTEMS defined in manifest:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
android.intent.action.MEDIA_MOUNTED action can be handled by privileged system application only. That action can not be received by 3rd party applications
May be when you create receiver dynamically your intent filter is different compared to when it is created through the <receiver/> tag? Could you show us both your manifest part and the code part?
Also, instead of storing data in receiver's fields, you could consider other options:
A content provider
Shared preferences
A singleton object
In that case there will be no difference between statically and dynamically created receivers.
EDIT: Based on the provided code, the problem is probably in priority setting:
Applications must use a value that is larger than SYSTEM_LOW_PRIORITY and smaller than SYSTEM_HIGH_PRIORITY .
SYSTEM_HIGH_PRIORITY = 1000
I have a little confusion with broadcast receivers. I have a broadcast receiver which is triggered upon TIME_SET and TIMEZONE_CHANGED actions (the code is given below). What I was wondering is, can OnDateTimeChanged (see the code below) be triggered simultaneously (and its execution overlaps) when both TIME_SET and TIMEZONE_CHANGED actions are triggered or is one always going to be triggered after the other? Based on some simple experiments I did, I got the impression that the two executions of OnDateTimeChanged are triggered consecutively with no time overlap but I cannot be 100% sure of this. If anyone has an idea I'll be very happy.
<!-- Excerpt from manifest -->
<receiver android:name=".OnDateTimeChanged">
<intent-filter>
<action android:name="android.intent.action.TIME_SET"/>
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
</intent-filter>
</receiver>
// Broadcast receiver class
public class OnDateTimeChanged extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// Do some work here
}
}
BTW, both TIME_SET and TIMEZONE_CHANGED can be triggered when under Settings - Date&Time you switch to the Automatic mode and this changes both the time and the timezone.
-Ali
Logically, they would all execute simultaneously. Physically, only one can occupy a core at a time and might finish before another starts. Under identical conditions,the behavior might appear to be consistent. The documentation itself describes it as, "All receivers of the broadcast are run in an undefined order, often at the same time."
If you want to give other receivers a chance to run, you can call Thread.yield().