I'm trying to create a reminder application that pops up a reminder in the status bar. As I understand, the Android NotificationManager is the standard tool to use to schedule notifications however a BootService is needed in order to re-schedule notifications as scheduled events do not survive across boots.
I've pieced together an application below which schedules a single reminder at boot time, and pops up a notification in the status bar. If you click the notification, it launches MainActivity which, in the future, will have options to add more reminders, delete them, or whatever.
The problem I'm having is that the reminder works correctly the first time however it seems to be re-scheduling itself and popping up again at random times for some reason. Should I be launching another activity rather than the one which installs the BootAlarmService?
UPDATE:
So I think I found some clues with logcat. Apparently the Service is crashing and being restarted which is resetting the Notification. Any ideas why this is?
UPDATE II : code changed to working model
ActivityManager I No longer want com.example.alarm_boot_test (pid 1428): hidden #16
ActivityManager W Scheduling restart of crashed service com.example.alarm_boot_test/.BootAlarmService in 5000ms
ActivityManager W Scheduling restart of crashed service com.example.alarm_boot_test/.NotificationAlarmService in 15000ms
ActivityManager I Start proc com.example.alarm_boot_test for service com.example.alarm_boot_test/.BootAlarmService: pid=2321 uid=10069 gids={}
dalvikvm D Debugger has detached; object registry had 1 entries
szipinf D Initializing inflate state
BootAlarmService D oncreate()
BootAlarmService D alarm set for Thu Jan 17 08:03:00 CST 2013
MainActivity.java
package com.example.alarm_boot_test;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity
{
#Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
}
}
BootAlarmService.java
package com.example.alarm_boot_test;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class BootAlarmService extends Service
{
private final String TAG = this.getClass ().getName ();
#Override
public void onCreate ()
{
Log.d (TAG, "oncreate()");
super.onCreate ();
}
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
Log.d (TAG, "alarm_test: BootAlarmService.onStartCommand() Received start id " + startId + ": " + intent);
// if intent == null, service has been killed/restarted by system
if (intent != null)
createNotificationOnBoot();
else
Toast.makeText (getBaseContext (), "Intent was null in BootAlarmService.", Toast.LENGTH_LONG).show();
return START_STICKY;
}
private void createNotificationOnBoot ()
{
Intent inotify = new Intent(this , NotificationAlarmService.class);
inotify.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmManager amgr = (AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, inotify, 0);
// go off two mins from now
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, calendar.get (Calendar.MINUTE) + 2);
amgr.set (AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis (), pendingIntent);
Log.d (TAG, "alarm set for " + calendar.getTime ().toString ());
}
#Override
public IBinder onBind (Intent intent)
{
return null;
}
}
BootReceiver.java
package com.example.alarm_boot_test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootReceiver extends BroadcastReceiver
{
#Override
public void onReceive (final Context context, final Intent bootintent)
{
Intent i = new Intent ();
i.setAction ("com.example.alarm_boot_test.BootAlarmService");
context.startService (i);
}
}
NotificationAlarmService.java
package com.example.alarm_boot_test;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class NotificationAlarmService extends Service
{
private final String TAG = this.getClass().getName ();
#Override
public void onCreate ()
{
super.onCreate ();
}
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
Log.d (TAG, "alarm_test: NotificationAlarmService.onStartCommand()");
if (intent != null)
createNotification ();
else
Toast.makeText (getBaseContext (), "Intent was null in NotificationAlarmService.", Toast.LENGTH_LONG).show();
return super.onStartCommand (intent, flags, startId);
}
private void createNotification()
{
NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Notification notification = new Notification(android.R.drawable.stat_sys_warning, "Note from AlarmService", System.currentTimeMillis());
Intent i = new Intent(this, ViewReminder.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0);
notification.setLatestEventInfo(this, "New Notification", "You have been notified by AlarmService", pendingIntent);
notificationManager.notify(10001, notification);
}
#Override
public IBinder onBind (Intent intent)
{
return null;
}
}
*activity_main.xml*
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Service started! Reboot!" />
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.alarm_boot_test"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="9" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service android:name="com.example.alarm_boot_test.BootAlarmService" >
<intent-filter>
<action android:name="com.example.alarm_boot_test.BootAlarmService" >
</action>
</intent-filter>
</service>
<receiver android:name="com.example.alarm_boot_test.BootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" >
</action>
</intent-filter>
</receiver>
<service android:name="com.example.alarm_boot_test.NotificationAlarmService" >
</service>
<activity
android:name="com.example.alarm_boot_test.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>
</application>
</manifest>
In case it helps someone else, I think I needed to check the passed Intent for NULL in the onStartCommand() method both in BootAlarmService.java as well as NotificationAlarmService.java. Only been testing it a couple days but it looks like the Intent is NULL if the system kills/restarts the service. Simply testing for this allowed me to create the notification only when the service is started at Boot-time (when the passed Intent is NOT null).
Related
I am trying to create a Service application without a UI/Activity.
The service will start on BOOT_COMPLETED. Currently I am experiencing an issue when the receiver service cannot start the main service.
The error sound like that (Android Device Monitor):
Tag: Activity Manager
Text: Unable to start service Intent { cmp=com.remote.cat/.ActionService } U=0: not found
My android OS version on the device is 4.2.2
I am testing it via this command in PowerShell:
adb.exe shell am broadcast -a android.intent.action.BOOT_COMPLETED -n com.remote.cat/.AutoStartServiceReceiver
Both services are in the root of the package com.remote.cat
Feel like I am missing a small thing or having a typo, would greatly appreciate any help!
Thank you!
Here is the code of the manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.remote.cat"
android:installLocation="internalOnly">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:allowBackup="true" android:label="#string/app_name"
android:icon="#mipmap/ic_launcher" android:theme="#style/AppTheme">
<receiver android:name="com.remote.cat.AutoStartServiceReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
<service android:name="com.remote.cat.AutoStartServiceReceiver"></service>
<service android:name="com.remote.cat.ActionService"></service>
</manifest>
Here is the brodcastreceiver class:
package com.remote.cat;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AutoStartServiceReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED))
{
Intent serviceIntent = new Intent(context, ActionService.class);
//Intent serviceIntent = new Intent("com.remote.cat.ActionService");
context.startService(serviceIntent);
}
}
}
Here is the main service that I am trying to start:
package com.remote.cat;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
import java.util.TimerTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ActionService extends Service
{
private ScheduledThreadPoolExecutor executor = null;
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
executor = new ScheduledThreadPoolExecutor(4);
final ScheduledFuture<?> handle = executor.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "one minute message", Toast.LENGTH_LONG).show();
}
}, 0, 8, TimeUnit.SECONDS);
return START_STICKY;
}
}
Change your AutoStartServiceReceiver declaration in the manifest to be a <receiver> rather than <service>.
The error is in your broadcastreceiver class
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED))
it should be
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
EDIT
I believe you have to declare your services inside the application tag since it is a part of the application
I want to create an Android application which performs some action periodically (every minute) in the background. The application shall have no user interface, therefore there will be no Action-Class. It shall start automatially after boot.
I have coded my Application as shown below, but it just does not start after boot? Can anyone help?
I am using a Samsung Tablet GT-P5200 with Android 4.4.2
Many thanks for your help in advance.
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.somecompany.justoneservice" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name=".BootReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" >
</service>
</application>
</manifest>
BootReceiver.java
package com.somecompany.justoneservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.text.format.DateUtils;
import android.util.Log;
public class BootReceiver extends BroadcastReceiver {
public BootReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG", "BOOT");
long interval = DateUtils.MINUTE_IN_MILLIS * 1;
long firstStart = System.currentTimeMillis() + interval;
Intent mainServiceIntent = new Intent(context, MyService.class);
PendingIntent mainServicePendingIntent = PendingIntent.getService(context, 0, mainServiceIntent, 0);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setInexactRepeating(AlarmManager.RTC, firstStart, interval, mainServicePendingIntent);
}
}
MySevice.java
package com.somecompany.justoneservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
public MyService() {
}
#Override
public void onCreate() {
super.onCreate();
Log.d("TAG", "Service created.");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TAG", "Service started. (" + startId + ")");
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d("TAG", "Service started.");
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
The application shall have no user interface, therefore there will be no Action-Class.
Newly-installed apps' manifest-registered receivers are disabled until something uses an explicit Intent to start one of your components. Usually, this is the user tapping on the icon for one of your activities in a home screen's launcher. And usually that is not a problem, because all apps need an activity, to allow the user to configure the behavior of the app, get help, read the license agreement terms, etc.
In some scenarios, something other than a home screen launcher icon can start up one of your components with an explicit Intent. For example, if you are a plugin to some other app, that other app might detect your installation and start up one of your components.
But, if nothing will start one of your components with an explicit Intent, then your BOOT_COMPLETED receiver will never get control, even after a reboot.
I have stuck with an issue of running a service when force stop is clicked and when i restart my mobile the service should be invoked.I have followed some examples but i cant able to achieve the task.Can any one guide me to achieve the task.
Required:
1.Service should run when force stop has been clicked from settings
2.Service should run when mobile has been restarted.
TestActivity.java
package com.testsearching;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class TestActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
startService(new Intent(this, ServiceTest.class));
}
}
ServiceTest.java
package com.testsearching;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class ServiceTest extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mTimer = new Timer();
mTimer.schedule(timerTask, 2000, 2 * 1000);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
} catch (Exception e) {
e.printStackTrace();
}
return super.onStartCommand(intent, flags, startId);
}
private Timer mTimer;
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
Log.e("Log", "Running");
}
};
public void onDestroy() {
try {
mTimer.cancel();
timerTask.cancel();
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent("com.android.techtrainner");
intent.putExtra("yourvalue", "torestore");
sendBroadcast(intent);
}
}
ReceiverCall.java
package com.testsearching;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class ReceiverCall extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Log.i("Service Stops", "Ohhhhhhh");
context.startService(new Intent(context, ServiceTest.class));;
Toast.makeText(context, "My start", Toast.LENGTH_LONG).show();
}
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testsearching"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:theme="#style/AppTheme" >
<activity
android:name="com.testsearching.TestActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ServiceTest" >
<intent-filter>
<action android:name="com.testsearching.ServiceTest" />
</intent-filter>
</service>
<receiver
android:name="ReceiverCall"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="com.android.techtrainner" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
In theory, this is not possible; according to the Android security model.
As Panaj Kumar points out in the comments:
When user does force stop, means he does not want to run this
application (any component). he is not interested anymore, and this
is rights of user. SO android does not gives a way to keep running
your service, even after forced close your app.
Android will prevent the app from restarting using the START_STICKY flag, and will disable the RECEIVE_BOOT_COMPLETED receiver. The system will also disable all Alarms that have been set for this app.
Before the system will allow the app to run again, the user must run an Activity of the app themselves.
That said, it seems that certain apps are still able to break the rules in this way. This should be considered incorrect and would be taking advantage of a security hole, however it shows that it is still possible, even on KitKat.
The Discovery Insure driving app seems to be able to restart itself when it has been force stopped, and will restart on boot:
Discovery Insure Driving Challenge on Play Store
However, this functionality should not be relied on - hopefully this security flaw will be fixed in future system updates.
Write this on in your OnCreate of the main launching activity
if(!isMyServiceRunning(ServiceClass.class))
context.startService(new Intent(context.getApplicationContext(),ServiceClass.class));
here is the running service check function
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
and Create your service with this architecture.Observe the return START_STICKY
public class ServiceClass extends IntentService {
public ServiceClass()
{
super("null");
}
public Context context;
public Intent intent;
public Date currentTime;
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
onHandleIntent(intent);
return START_STICKY;
}
#Override
protected void onHandleIntent(#Nullable Intent intnt) {
currentTime = Calendar.getInstance().getTime();
context = getApplicationContext();
this.intent = intnt;
Log.d("ServiceClass","Service class running "+ currentTime);
}
}
I'm currenty devepoling an Android Application that remembers the user to a daily action.
The idea is, that the app gives a notification to the user if he did not already performed the action. The notification should appear every day at i.e. 3PM.
My Question is, how I can implement the check. I already found tutorials about how to use AlarmManager and NotificationManager, but these would remember the user even, if he already is finished.
Is there a way to start the check instead of the Notification, and if the check says there should be a notification, it is published?
You could save a shared preference that indicated the last time the user had completed the daily action. The when your alarm fires, you start a service that checks the status of the shared preference. If it was less than 1 day ago, then the user has done the daily action today.
Here's how you'd check:
SharedPreferences settings = getSharedPreferences(MainActivity.PREFS, MODE_PRIVATE);
if (System.currentTimeMillis() - settings.getLong("lastTimeActionDone", 0) < MILLISECS_PER_DAY) {
// Action done within last day
} else {
// Action not done within last day
}
Here's how you'd save the last time the action had been done:
SharedPreferences settings = getSharedPreferences(MainActivity.PREFS, MODE_PRIVATE);
SharedPreferences.Editor editor = null;
editor.putLong("lastTimeActionDone", System.currentTimeMillis());
editor.commit();
EDIT:
Here's a sample app that does most of what you want. As written, it just wakes up at the same time each day with that time being the time of day that the app was last started. So the one major piece missing is to make the alarm wake at a specific time each day. To get that part working, you'd need to a little date-time arithmetic when setting the (first) alarm time.
MainActivity.java:
package com.example.dailycheck;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
public final static String PREFS = "PrefsFile";
private SharedPreferences settings = null;
private SharedPreferences.Editor editor = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
// Save time of run:
settings = getSharedPreferences(PREFS, MODE_PRIVATE);
editor = settings.edit();
// First time running app?
if (!settings.contains("lastTimeActionDone"))
enableNotification(null);
Log.v(TAG, "Starting CheckRecentRun service...");
startService(new Intent(this, CheckActionDone.class));
}
public void doAction(View v) {
Log.v(TAG, "Recording time action done");
editor.putLong("lastTimeActionDone", System.currentTimeMillis());
editor.commit();
}
public void enableNotification(View v) {
editor.putBoolean("enabled", true);
editor.commit();
Log.v(TAG, "Notifications enabled");
}
public void disableNotification(View v) {
editor.putBoolean("enabled", false);
editor.commit();
Log.v(TAG, "Notifications disabled");
}
}
CheckActionDone.java:
package com.example.dailycheck;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;
public class CheckActionDone extends Service {
private final static String TAG = "CheckRecentPlay";
private static Long MILLISECS_PER_DAY = 86400000L;
private static long delay = 60000; // 1 minute (for testing)
// private static long delay = MILLISECS_PER_DAY; // 1 day
#Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "Service started");
SharedPreferences settings = getSharedPreferences(MainActivity.PREFS, MODE_PRIVATE);
// Are notifications enabled?
if (settings.getBoolean("enabled", true)) {
// And was action not recently done?
Long lastTimeDone = settings.getLong("lastTimeActionDone", 0);
if ((System.currentTimeMillis() - lastTimeDone) >= delay) {
sendNotification();
} else {
Log.i(TAG, "Action recently done");
}
} else {
Log.i(TAG, "Notifications are disabled");
}
// Set an alarm for the next time this service should run:
setAlarm();
Log.v(TAG, "Service stopped");
stopSelf();
}
public void setAlarm() {
Intent serviceIntent = new Intent(this, CheckActionDone.class);
PendingIntent pi = PendingIntent.getService(this, 131313, serviceIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pi);
Log.v(TAG, "Alarm set");
}
public void sendNotification() {
Intent mainIntent = new Intent(this, MainActivity.class);
#SuppressWarnings("deprecation")
Notification noti = new Notification.Builder(this)
.setAutoCancel(true)
.setContentIntent(PendingIntent.getActivity(this, 131314, mainIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setContentTitle("Action Not Do")
.setContentText("You didn't do the daily action.")
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.drawable.ic_launcher)
.setTicker("You haven;t done the daily action; please do it now.")
.setWhen(System.currentTimeMillis())
.getNotification();
NotificationManager notificationManager
= (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(131315, noti);
Log.v(TAG, "Notification sent");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
main_activity.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doAction"
android:text="#string/do_action" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="enableNotification"
android:text="#string/enable" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="disableNotification"
android:text="#string/disable" />
</LinearLayout>
strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Come Back</string>
<string name="do_action">Do Action</string>
<string name="enable">Enable Notifications</string>
<string name="disable">Disable Notifications</string>
</resources>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.dailycheck"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.dailycheck.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>
<service
android:name="com.example.dailycheck.CheckActionDone" >
</service>
</application>
</manifest>
I have:
MyApp extends Application with onCreate:
sendBroadcast(refreshAlarm);
Log.d(TAG, "broadcast sent with intent " + refreshAlarm);
Log.d(TAG, "onCreate");
where
static final Intent refreshAlarm = new Intent(ACTION_REFRESH_RECEIVER);
public static final String ACTION_REFRESH_RECEIVER = "com.example.myapp.REFRESH_RECEIVER";
BroadcastReceiver :
package com.example.myapp;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.preference.PreferenceManager;
import android.util.Log;
public class RefreshReceiver extends BroadcastReceiver
{
private static final String TAG = "RefreshReceiver";
#Override
public void onReceive(Context context, Intent intent)
{
Log.d(TAG, "broadcast received with intent " + intent);
long interval = Long
.parseLong(PreferenceManager.getDefaultSharedPreferences(
context).getString("delay", "900")) * 1000;
PendingIntent operation = PendingIntent.getService(context, -1,
new Intent(context, RefreshService.class),
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(operation);
if (interval > 0)
{
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), interval, operation);
}
Log.d(TAG, "onReceive: delay = " + interval);
}
}
declared in manifes:
<receiver android:name="com.example.myapp.RefreshReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="com.example.myapp.REFRESH_RECEIVER" />
</intent-filter>
</receiver>
It seems to me that I have all I need to make this work. Broadcast is send in onCreate (I can see in log it is indeed send). Broadcast is declared with intent filter to receive refreshAlarm intent, but it doesn't receive it and I cannot figure out why. Do I need anything else?
if you put BroadCastReceiver in mainfest.xml you don't need to regiter it in code , register it in code only if you create it in your Code
this is example here :
<receiver android:name="MyReceiver" >
<intent-filter>
<action android:name="android.mybroadcast" />
</intent-filter>
</receiver>
and here to call it from your class file ,
Intent intent = new Intent();
intent.setAction("android.mybroadcast");
sendBroadcast(intent);
try to register your broadcast receiver by programmatically
public void registerBroadcastReceiver(View view) {
this.registerReceiver(broadCastReceiver, new IntentFilter(
"com.example.myapp.REFRESH_RECEIVER"));
Toast.makeText(this, "Enabled broadcast receiver", Toast.LENGTH_SHORT)
.show();
}
and unregister by this
public void unregisterBroadcastReceiver(View view) {
this.unregisterReceiver(broadCastReceiver);
Toast.makeText(this, "Disabled broadcst receiver", Toast.LENGTH_SHORT)
.show();
}
It could be possible that its not working because your Receiver and the package name you are using for registering in your manifest do not match.
Make sure that your package name matches your respective package for your receiver.
You said
MyApp extends Application
you should register MyApp as application in android manifest.
put this line in android manifest application element
android:name="your.package.MyApp"
Where your.pacakage is the package where MyApp file is located. Now your application element should look as follows
<application
android:name="your.package.MyApp"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/yourTheme" >
I had the same problem. It seems that the registered broadcastreceivers only work for system actions. With my custom action it only worked as long as my app was running (activity was in activity stack).
My workaround is to create an activity for it. This does not work in background, however it gives you the possibility to catch events from other apps
<activity android:name=".ImportToProActivity">
<intent-filter>
<action android:name="com.sourcecastle.logbook.ImportToProActivity"/>
</intent-filter>
</activity>
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.sourcecastle.freelogbook", "com.sourcecastle.logbook.ImportToProActivity"));
startActivity(intent);