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
Related
I am learning about BroadCastReceiver. What I am trying to achieve with the following piece of code is, I would like to see a Toast when I switch to airplane mode, where the app is on or not. What am I not doing / Doing wrong? Please Help. Thanks
ConnectivityChangedReceiver.java class
public class ConnectivityChangedReceiver extends BroadcastReceiver {
#Override
public void onReceive( Context context, Intent intent ){
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.kirathe.mos.c_max">
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SEND_SMS"/>
<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=".ConnectivityChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE">
</action>
</intent-filter>
</receiver>
</application>
MainActivity.java`
public class MainActivity extends AppCompatActivity {
private TextView switchStatus;
private Switch mySwitch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
From the android documentation :
https://developer.android.com/guide/components/broadcast-exceptions
As part of the Android 8.0 (API level 26) Background Execution Limits,
apps that target the API level 26 or higher can no longer register
broadcast receivers for implicit broadcasts in their manifest.
However, several broadcasts are currently exempted from these
limitations. Apps can continue to register listeners for the following
broadcasts, no matter what API level the apps target.
and
https://developer.android.com/distribute/best-practices/develop/target-sdk
Google Play will require that new apps target at least Android 8.0
(API level 26) from August 1, 2018, and that app updates target
Android 8.0 from November 1, 2018.
"android.intent.action.AIRPLANE_MODE" is no longer in the list of exempted broadcasts. So, register your broadcast receiver in activity rather than in AndroidManifest.
The Official document of Broadcast Receivers Says:
android:exported
Whether or not the broadcast receiver can receive messages from sources outside its application — "true" if it can, and "false" if not. If "false", the only messages the broadcast receiver can receive are those sent by components of the same application or applications with the same user ID.
Try it like this,try adding,android:exported="true":
//Add this permission too
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<receiver android:enabled="true" android:name=".ConnectivityChangedReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.ACTION_AIRPLANE_MODE_CHANGED"/>
</intent-filter>
</receiver>
The Real state is determined like this:
#Override
public void onReceive(Context context, Intent intent) {
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
if(isAirplaneModeOn){
// handle Airplane Mode on
} else {
// handle Airplane Mode off
}
}
So I just found the solution to my problem above.
I changed
<receiver android:name=".ConnectivityChangedReceiver">
to
<receiver android:name="ConnectivityChangedReceiver">
(Without the '.' at the beginning of name. Hope it helps a stranded one!
if you API level greater than 26 you should add permission to your code like that:
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val _receiver = cSmsListener() //<--you BroadCastreciever class
val intentFilter = IntentFilter()
intentFilter.addAction(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)
getApplicationContext().registerReceiver(_receiver, intentFilter);
var myPermission: Array<String> = arrayOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS)
ActivityCompat.requestPermissions(this, myPermission,1)
intent- filter is not working in the receiver tag in AndroidManifest.xml file for me. So I added everything in MainActivity.java file like this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter("android.intent.action.AIRPLANE_MODE");
broadcastBattery bb = new broadcastBattery();
registerReceiver(bb, intentFilter);
}
Now everything is working fine.
You have to enable your broadcast in your manifest.xml file :
<receiver android:enabled="true" android:name=". ConnectivityChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>
You need to put the receiver in the bundles package:
package my.bundles.id;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;
public class ConnectivityChangedReceiver extends BroadcastReceiver {
#Override
public void onReceive( Context context, Intent intent )
{
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
}
}
You should put it in a package thats the same as the bundleId and that will let the above work. The first dot in the name field means that the Class is a member of the bundles namespace. So, since it wasnt in a package, the dot made it look in the wrong place.
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
Hello i would to develop a simple app without Main Activity as launcher.
I want to register a broadcast receiver which starts after reboot of device and inside OnReceive callback starts an Activity
Here my manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.examples"
android:versionCode="1"
android:versionName="1.0"
>
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="18" />
<application android:label="#string/app_name" android:icon="#drawable/ic_launcher">
<receiver android:name=".AfterRebootBR" android:exported="false"
android:label="Boot Notification Receiver" android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity android:name=".MainActivity"
android:label="#string/app_name">
</activity>
</application>
</manifest>
And here my Broadcast receiver
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package it.examples;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class AfterRebootBR extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("AfterRebootBR","***************** ON RECEIVE *********************");
Log.e("AfterRebootBR","***************** ON RECEIVE *********************");
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
And finally the MainActivity
package it.examples;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
What is wrong in my code?
Thanks in advance
Francesco
my code is working..here is it...
in manifest
<receiver
android:name="com.calender.calenderevent.Reboot_Reciever"
android:enabled="true"
android:exported="true"
android:label="BootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" >
</action>
</intent-filter>
</receiver>
I cant see anything wrong with your code, however i have something worth to try.
Move the permission out of the application tag :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
If its not working, simplify the receiver :
<receiver android:name=".AfterRebootBR">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Still not working? Try to add some delay, as mentioned here :
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
//run your service
}
}, 10000);
Quoted from the link above :
While, I suggestion to delay several seconds, e.g., 10 seconds, before
running the (1) line, which is more stable for different phones and
services.
For example, in my case, my service is going to write sd card. If you
start your service immediately, some phones may fail because the sd
card is not ready.
Starting with android 3.1 you cannot have a broadcast receiver to get spawned by the application service manager if it has no context in active state (aka. at least an activity or service that is keeping the process in an "active state")
Excerpt from specification
Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents.
It does this to prevent broadcasts from background services from inadvertently or
unnecessarily launching components of stoppped applications. A background service or
application can override this behavior by adding the FLAG_INCLUDE_STOPPED_PACKAGES
flag to broadcast intents that should be allowed to activate stopped applications.
Applications are in a stopped state when they are first installed but are not yet
launched and when they are manually stopped by the user (in Manage Applications).
You need to somehow start your application, and then send it in a dormant state (but registered in the app manager). You can use a service for this.
It is strongly NOT recommended to start Activity from BroadcastReciever:
https://developer.android.com/training/run-background-service/report-status.html#ReceiveStatus
Never start an Activity in response to an incoming broadcast Intent.
In my case PackageManager.DONT_KILL_APP helped:
https://developer.android.com/training/scheduling/alarms.html#boot
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
I've experimented with MIUI 8 firmware real device Xiaomi Redmi Note 3.
My findings are:
you have to add app to autorun to enable it be fired by broadcast. I've checked it with such serious apps as Viber, WhatsApp.
I've compared with manifest settings (without enabling reciever programmatically):
<receiver
android:name=".activities.broadcastrecievers.CallReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
I'm writing an application that needs to receive wifi state modification. To do it I've wrote a class, TestReceiver, that extends BroadcastReceiver and, now, write on Log.i.
The receiver has been registrated via AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lazooo.wifi_finder_service">
<uses-sdk android:minSdkVersion="14"/>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<user-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<user-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<receiver android:name=".TestReceiver">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
</application>
and my TestReceiver is:
package com.lazooo.wifi_finder_service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class TestReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("BroadcastApplication", "ricevuto capo");
Toast.makeText(context, "ciao", Toast.LENGTH_LONG).show();
}
}
The matter is that it doesn't work, when I turn on/off wifi it doesn't do nothing. What am I missing?
Debug and see if anything is being sent. If the send is fine and you are still not receiving the message, my experience has been that with wifi, firewall issues may kick in and the message is not received. Any kind of notification seems to work better with data connectivity.
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">