I'm trying to write a simple app to capture the ACTION_NEW_OUTGOING_CALL intent and write some debugging information.
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.apis"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name="DialerReceiver" android:exported="false" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses-permission>
</manifest>
And here is the code for DialerReceiver:
package com.example.android.apis;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class DialerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
debugOut("arg0: " + arg0.toString());
debugOut("arg1: " + arg1.toString());
debugOut("isOrderedBroadcast = " + isOrderedBroadcast());
}
private static void debugOut(String str) {
Log.i("DialerReceiver", str);
}
}
For reasons that I do not understand, when I install this and initiate an outgoing call, I get the following error:
WARN/ActivityManager(59): Permission Denial:
broadcasting Intent { act=android.intent.action.NEW_OUTGOING_CALL (has extras) }
from com.android.phone (pid=123, uid=1001) requires null
due to receiver com.example.android.apis/com.example.android.apis.DialerReceiver
What gives? It seems like PROCESS_OUTGOING_CALLS should be sufficient.
FWIW, if I change to a notification without permissions (TIMEZONE_CHANGED, for example), this works like a charm.
Thanks in advance.
Answering my own question.
After reviewing my manifest, it seemed like android:exported="false" was incorrect, since Android itself would need to invoke DialerReceiver.
When I changed this to android:export="true", everything worked just fine.
FWIW, I did this against the emulator (API version 8 and version 10 devices).
I am also intercepting outgoing calls to take an action. I also only have the added permission, PROCESS_OUTGOING_FILES, but I did notice that in my DialerReceiver declaration I am setting a priority:
<receiver
android:name="DialerReceiver"
android:enabled="true">
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
This setup works fine for me. I can post some code from the DialerReceiver class if you need it. Are you testing this against an emulator or a phone? I have only tested against an actual phone. I am not using an emulator.
Hope this helps.
Related
I have a with Broadcastreceiver with an intent-filter to catch android.intent.action.NEW_OUTGOING_CALL.
I read many tutorials and answer here about handling NEW_OUTGOING_CALL intent, but I was unable to make this thing works.
My goal is to log intent android.intent.action.NEW_OUTGOING_CALL received by my Broadcastreceiver. I'm unable to make this simple thing works.
Here's my code:
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.vannus.broadcasttest">
<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: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=".TestReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
</manifest>
This is the code for the Broadcastreceiver (TestReceiver.java)
package net.vannus.broadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class TestReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Log.w("###TEST###",intent.getAction());
}
}
The project also contains an empty MainActivity with no functionality.
Executing the project the main activity is launch, but no log are written when I try to make or receive calls.
I tested the code in the emulator (Android 7) and on a Motorola G4 phone (Android 6.0), but nothing was logged on logcat.
I'm using Android Studio 2.3
What am I doing wrong?
Thanks
Vannus
From android Oreo the problem is that for "dangerous" type permissions (of which PROCESS_OUTGOING_CALLS" is one), it is not enough to declare then in the manifest. You need to specifically prompt the user to grant this permission. This can be done using the framework as discussed here:
https://developer.android.com/training/permissions/requesting
Specifically you need to basically call "requestPermissions" with an array of the permissions you actually need and it will ask the user to approve them.
Personally I find it quite annoying but I get the rationale behind it.
The solution is very simple.... on the phone go to settings-> apps select application and give phone permission.
The clue came when searching the logcat I found this error
03-05 20:18:57.090 1547-1775/system_process W/BroadcastQueue: Permission Denial: receiving Intent { act=android.intent.action.NEW_OUTGOING_CALL flg=0x10000010 (has extras) } to net.vannus.broadcasttest/.TestReceiver requires android.permission.PROCESS_OUTGOING_CALLS due to sender android (uid 1000).
in my case, app had the permissions already, but for some reason when i declared
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter
after android.intent.action.NEW_OUTGOING_CALL, the receiver started sending out the new outgoing call event.
so the declaration looks like this :
<receiver android:name=".CallReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Check for permission run time
#TargetApi(Build.VERSION_CODES.M)
public static boolean hasSelfPermission(Activity activity, String[] permissions) {
// Below Android M all permissions are granted at install time and are already available.
if (!isMNC()) {
return true;
}
// Verify that all required permissions have been granted
for (String permission : permissions) {
if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
and use this method to check permission
#TargetApi(Build.VERSION_CODES.M)
private boolean isReadStatePermission() {
if (hasSelfPermission((Activity) context, READ_PHONE_STATE)) {
return true;
} else {
if (((Activity) context).shouldShowRequestPermissionRationale(Manifest.permission.READ_PHONE_STATE)) {
((Activity) context).requestPermissions(READ_PHONE_STATE, REQUEST_WRITE_STORAGE);
} else {
((Activity) context).requestPermissions(READ_PHONE_STATE, REQUEST_WRITE_STORAGE);
}
return false;
}
perform any operation after checking the permission
if (isReadStatePermission()) {
PERFROM YOUR OPERATION
}
I am listening to deskclock alarm change intent using my broadcast receiver. When the onReceive() method in my Broadcast Receiver is called, the logs (Log.i/v()) inside the onReceive are not getting printed on Android monitor but Toasts are working just fine.
Manifest File :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dumbrella.ratemyday">
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<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:process=":remote" android:name="AlarmClockReceiver">
<intent-filter>
<action android:name="com.android.deskclock.ALARM_DISMISS" />
<action android:name="com.android.deskclock.ALARM_SNOOZE" />
<action android:name="com.android.deskclock.ALARM_ALERT" />
<action android:name="com.android.deskclock.ALARM_DONE" />
</intent-filter>
</receiver>
</application>
</manifest>
Broadcast Receiver:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import java.text.SimpleDateFormat;
public class AlarmClockReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// This log.v does not get printed on Android Monitor
Log.v("Broadcast Test", "In Broadcast Listener");
String message = "Broadcast intent detected "
+ intent.getAction();
// This toast gets displayed after the alarm is dismissed
Toast.makeText(context, message,Toast.LENGTH_LONG).show();
}
}
Maybe it's too late, but I leave it for future programmers with this problem, I had a similar problem and solved it this way.
Simply in Logcat panel, change the filtering listbox to "No Filters".
You might want to make sure that you have selected the correct device in your DDMS perspective, also ensure that you have selected the correct filtering option and log level - in your case you want to select "verbose". Also check out the selected answer and suggestions as to why Logcat is not displaying logs.
You can filter logs to show BroadcastReceiver logs in LogCat Filter Configuration section:
The complete solution steps: Logs/logcat not working in BroadcastReceiver
Problem:
I am willing to create an application that simply starts as a background process and whenever a new message comes into the device it should log it into a file or simply display a toast message.
I have read a lot of blogs and tried to follow the steps as mentioned. But, I keep on sending messages on my device and nothing displayed not even in device log. I want to run it on devices from Froyo to Lollipop. So, I am not willing to use new Telephony API which supports API 19 and later versions.
Manifest File
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abc.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".SMSHandler">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Source File
package com.abc.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class SMSHandler extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast toast = Toast.makeText(context, "message initiated",
Toast.LENGTH_LONG);
toast.show();
if (intent.getAction()
.equals("android.provider.Telephony.SMS_RECEIVED")) {
toast = Toast.makeText(context, "message received",
Toast.LENGTH_LONG);
toast.show();
}
}
}
Environment:
IDE:
Android Studio
Min SDK Version:
8
Tested On:
ICS Device (Sony Xperia U)
Kit-Kat (MOTO G)
You need to add an activity, then run that activity, before this BroadcastReceiver will work.
More accurately, something needs to use an explicit Intent before your app will be moved out of the stopped state and allow manifest-registered BroadcastReceivers to work. The simplest way to do that is to have a launcher activity, and run that activity from the launcher.
To learn more, see "Launch controls on stopped applications" in the Android 3.1 release notes, along with this blog post.
Your Code look like this in manifest file
<receiver android:name=".SMSHandler"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
Add the following to your<receiver> in the manifest:
android:enabled="true"
android:exported="true">
Furthermore, according to this thread, it seems that you have to manually start one of your activities before the broadcast receiver will start working, i.e. the application has to have been launched at least once before any broadcast receiver will work.
I have been working on an app to respond to received SMS messages (before you complain, I know this has been asked A LOT, but believe me, I can't get it to work at all, and I've tried searching for hours). I've got my manifest set up like so:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.csbctech.notiscreen"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".NotiScreenActivity"
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="NotiScreenSmsReceiver" android:process=":remote">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
</manifest>
And my receiver class looks like this:
package com.csbctech.notiscreen;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.PowerManager;
import android.util.Log;
public class NotiScreenSmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.w("NotiScreen", "Got SMS");
}
}
But the "NotiScreenSmsReceiver" class never gets called. I've tried several different examples, and I can't for the life of me get the receiver class to get called...I've even tried removing the uses-permission, and I don't even get an error message about not having permissions. What could be wrong? Oh please help me, you're my only hope!
Are you running this on a phone with a custom SMS app such as GOSMS? I've heard that some of those programs will stop the broadcast so that they can create their own notifications and stop the stock ones.
Change
<receiver android:name="NotiScreenSmsReceiver" android:process=":remote">
to
<receiver android:name=".NotiScreenSmsReceiver" android:process=":remote">
I would like to write an application that is triggered when a calendar reminder occurs. I realize there is no officially documented way of doing this, but I have seen in the log that when my calendar alarm goes off on my phone (Droid X), AlertReceiver indicates that it has received an android.intent.action.EVENT_REMINDER:
01-03 11:03:00.029 D 1523 AlertReceiver onReceive: a=android.intent.action.EVENT_REMINDER Intent { act=android.intent.action.EVENT_REMINDER dat=content://com.android.calendar/129407058000 flg=0x4 cmp=com.android.calendar/.AlertReceiver (has extras) }
So, I set up a simple BroadcastReceiver:
package com.eshayne.android;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class CalendarTest extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
android.util.Log.i("CalendarTest", "CalendarTest.onReceive called!");
}
}
with this manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.eshayne.android"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.READ_CALENDAR" />
<application android:icon="#drawable/icon" android:label="#string/app_name" android:debuggable="true">
<receiver android:name="com.eshayne.android.CalendarTest">
<intent-filter>
<action android:name="android.intent.action.EVENT_REMINDER" />
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>
Unfortunately, when I put this on my phone and set up a calendar event with a reminder - when the reminder alerts, I still see the AlertReceiver log entry, but not mine.
I have also read here about some system intents that require registering via code rather than in the manifest. So, I tried the following instead:
package com.eshayne.android;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
public class CalendarTestDisplay extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
android.util.Log.i("CalendarTestDisplay", "received broadcast");
}
},
new IntentFilter("android.intent.action.EVENT_REMINDER"));
}
}
with this modified manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.eshayne.android"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.READ_CALENDAR" />
<application android:icon="#drawable/icon" android:label="#string/app_name" android:debuggable="true">
<activity android:name=".CalendarTestDisplay"
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>
<uses-sdk android:minSdkVersion="8" />
</manifest>
with no better result.
Any ideas what I may be missing? Or any other ideas of how I might be able to capture calendar alarm occurrences?
Thanks,
Ethan
You need to set data scheme to "content" in the intent filter.
Using manifest, add data element inside intent-filter
<receiver android:name="com.eshayne.android.CalendarTest">
<intent-filter>
<data android:scheme="content"/> <!-- this was missing -->
<action android:name="android.intent.action.EVENT_REMINDER" />
</intent-filter>
</receiver>
Using code, add datascheme in one function call
IntentFilter filter = new IntentFilter(CalendarContract.ACTION_EVENT_REMINDER);
filter.addDataScheme("content"); // this was missing
registerReceiver(myRemindersReceiver, filter);
Well, what you're trying to do is not part of the Android SDK, mostly because the calendar is not part of the operating system.
That being said, at minimum, you will need to add a <data> element to your <intent-filter>, since the Intent has a Uri.
However, I'm reasonably certain that this will not work, since the Intent also specifically identifies a component (com.android.calendar/.AlertReceiver). AFAIK, that was in the Intent at the outset, and therefore the Intent will only be delivered to that component, ignoring all other routing rules. It's conceivable the listed component only showed up after Intent resolution, but I don't think that's how those log entries work.
It is possible to make the broadcast intent "android.intent.action.EVENT_REMINDER" work by specifying DataAuthority and DataScheme in your intent filter along with your intent action.You need to specify DataAuthority as "com.android.calendar" and DataScheme as "content".
the broadcast intent "android.intent.action.EVENT_REMINDER" only gets fired when an alarm notification needs to be posted for a reminder
set a notification for your EVENT (Eg: 10 minutes before the event) in order for the broadcast intent "android.intent.action.EVENT_REMINDER" to work