I have an application which starts a service when the widget is tapped.
This is the class for the widget:
public class PlayWidget extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int i = 0; i < appWidgetIds.length; i++) {
int currentWidgetId = appWidgetIds[i];
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.playwidget);
views.setTextViewText(R.id.bLevelText, "My widget");
Intent intent = new Intent(context, PlayService.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pending = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.imageButton11, pending);
appWidgetManager.updateAppWidget(currentWidgetId, views);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.imageButton11);
}
}
}
This is the manifest declaration for the Widget:
<receiver
android:name=".widget.PlayWidget"
android:icon="#drawable/play">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/playwidget_info" />
</receiver>
This is the manifest declaration for the Service:
<service android:name=".widget.PlayService"/>
The problem is that on Android 11, when the app is killed and i press the widget, the Service won't start anymore. Anyone has an idea on how can i fix this issue?
I have found an workaround for this issue, by calling a BroadcastReceiver from the OnUpdate function, and then starting the Service from the BroadcastReceiver :
Intent intent = new Intent();
intent.setAction(START_SERVICE);
intent.setClassName(StartServiceReceiver.class.getPackage().getName(), StartServiceReceiver.class.getName());
PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.imageButton11, pending);
This is the code for the BroadcastReceiver:
public class StartServiceReceiver extends BroadcastReceiver {
public static final String START_SERVICE= "start_service";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(START_SERVICE)) {
context.startService(new Intent(context, PlayService.class));
}
}
}
And the manifest declaration for the BroadcastReceiver:
<receiver android:name=".StartServiceReceiver" android:label="#string/app_name"/>
Related
I try to start a ForegroundService by an BroadcastReceiver on Boot. I have tried this on a device with Android 8 and on an emulated Android 10 device. Both work fine. The problem is, that this code does not work on my Android 10 Galaxy S9. I have debugged everything, my BroadcastReceiver and the OnStartCommand method but also if the BroadcastReceiver runs the code fine, the OnStartCommand method does not start running.
I have a mainActivity in which the user has to apply this Process so the app gets opened once before the BroadcastReceiver should work.
I tried almost every solution i found here but nothing worked for me.
I don't understand why this is working on some devices but not on each. I hope someone can help me!
My min API is 26.
BroadcastReceiver
public class Restarter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intentt = new Intent (context, MyService.class);
intentt.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startForegroundService(intentt);
} else {
Intent intentt = new Intent (context, MyService.class);
intentt.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(intentt);
}
}
}
Service
public class MyService extends Service {
public static final String CHANNEL_ID = "exampleServiceChannel";
#Override
public void onCreate() {
super.onCreate();
Log.d("WhereAreWe", "create");
createNotificationChannel();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.d("WhereAreWe", "StartCommand");
SharedPreferences check = getSharedPreferences("Checked", Context.MODE_PRIVATE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O){
Intent intents = new Intent(this, MainActivity.class);
intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intents, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "newid")
.setSmallIcon(R.drawable.ic_android)
.setContentTitle("Foreground Service")
.setContentText("Example text")
.setOngoing(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent);
startForeground(1, builder.build());
}else{
startForeground(1, new Notification());
}
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.MyApplication">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
.
.
.
<receiver
android:name=".Restarter"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="restartservice" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"
android:stopWithTask="false" />
</application>
</manifest>
I'm trying to make an app that monitors the users phone usage by tracking time of screen lock and unlock. I tried to setup a BroadcastReceiver which works fine when the app is running the background. But won't work when I close the app. Is there a solution for this.
The code I'm using now is as follows :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, ScreenListenerService.class);
startService(intent);
}
}
ScreenListenerService class is as follows..
public class ScreenListenerService extends Service {
private BroadcastReceiver mScreenStateBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// Save something to the server
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// Save something to the server
}
}
};
#Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenStateBroadcastReceiver, intentFilter);
}
#Override
public void onDestroy() {
unregisterReceiver(mScreenStateBroadcastReceiver);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
My AndroidManifest file is as follows :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abbinvarghese.calculu">
<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">
<service android:name=".ScreenListenerService" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
To overcome the imposed limitations of 8.0 you could run a foreground service. Just like a service but a notification is posted to the foreground.
Then the service code would be like this (remember to unregister the receiver onDestory):
BroadcastReceiver screenReceiver;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startRunningInForeground();
detectingDeterminateOfServiceCall(intent.getExtras());
registerBroadcastReceivers();
return START_STICKY;
}
private void startRunningInForeground() {
//if more than or equal to 26
if (Build.VERSION.SDK_INT >= 26) {
//if more than 26
if(Build.VERSION.SDK_INT > 26){
String CHANNEL_ONE_ID = "sensor.example. geyerk1.inspect.screenservice";
String CHANNEL_ONE_NAME = "Screen service";
NotificationChannel notificationChannel = null;
notificationChannel = new NotificationChannel(CHANNEL_ONE_ID,
CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setShowBadge(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager != null) {
manager.createNotificationChannel(notificationChannel);
}
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.background_running);
Notification notification = new Notification.Builder(getApplicationContext())
.setChannelId(CHANNEL_ONE_ID)
.setContentTitle("Recording data")
.setContentText("ActivityLog is logging data")
.setSmallIcon(R.drawable.background_running)
.setLargeIcon(icon)
.build();
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
notification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
startForeground(101, notification);
}
//if version 26
else{
startForeground(101, updateNotification());
}
}
//if less than version 26
else{
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Activity logger")
.setContentText("data recording on going")
.setSmallIcon(R.drawable.background_running)
.setOngoing(true).build();
startForeground(101, notification);
}
}
private Notification updateNotification() {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
return new NotificationCompat.Builder(this)
.setContentTitle("Activity log")
.setTicker("Ticker")
.setContentText("recording of data is on going")
.setSmallIcon(R.drawable.activity_log_icon)
.setContentIntent(pendingIntent)
.setOngoing(true).build();
}
private void detectingDeterminateOfServiceCall(Bundle b) {
if(b != null){
Log.i("screenService", "bundle not null");
if(b.getBoolean("phone restarted")){
storeInternally("Phone restarted");
}
}else{
Log.i("screenService", " bundle equals null");
}
documentServiceStart();
}
private void documentServiceStart() {
Log.i("screenService", "started running");
}
private void registerBroadcastReceivers() {
screenReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
switch (Objects.requireNonNull(intent.getAction())){
case Intent.ACTION_SCREEN_ON:
//or do something else
storeInternally("Screen on");
break;
case Intent.ACTION_SCREEN_OFF:
//or do something else
storeInternally("Screen off");
break;
}
}
};
IntentFilter screenFilter = new IntentFilter();
screenFilter.addAction(Intent.ACTION_SCREEN_ON);
screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenReceiver, screenFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(screenReceiver);
}
and call it from the main activity:
private void startServiceRunning() {
if(!isMyServiceRunning(Background.class)){
if(Build.VERSION.SDK_INT >25){
startForegroundService(new Intent(this, Background.class));
}else{
startService(new Intent(this, Background.class));
}
}
}
As Background Execution Limit imposes on Android 8.0 (API level 26) so now it's not possible to listen SCREEN_OFF and SCREEN_ON action in background by running the service.
I have found a work around for same with the help of JobScheduler which works fine for listen broadcast in background without running any service.
Please check on this: Screen OFF/ON broadcast listener without service on Android Oreo
Instead of creating a new service for broadcast receiver, you can directly create a broadcast receiver class that will listen to system broadcasts even when the app is not running.
Create a new class which extends BroadcastReceiver.
public class YourReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Do your stuff
}
}
And register it in manifest.
<receiver
android:name=".YourReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.ACTION_SCREEN_ON" />
<action android:name="android.intent.action. ACTION_SCREEN_OFF" />
<category android:name="android.intent.category.DEFAUL" />
</intent-filter>
</receiver>
Read about Manifest-declared receivers here.
Above solution won't work, here is the reason why. Problem is that your service is getting killed when the app is killed, so your receiver instance is removed from memory. Here is a little trick to re-start the service in background. Add the following code to your service.
#Override
public void onTaskRemoved(Intent rootIntent){
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
Although this is not the right way to do it. Also in Android 26+ you won't be able to do this and you'd go for foreground service. https://developer.android.com/about/versions/oreo/background
I'm working on app which test state on server every 15 min and push notification , i used Alarm Manager , broadcast receiver & Intent Service .
every thing worked fine and i get this state from server perfectly when app is running or in background , until i removed it from recent apps, every thing stops and can't get that state from server.
I searched ... and get nothing , but my friend tell me that I must register my broadcast receiver in on create of class extend from application.
I don't know how to do this .. so I need help please
Main Activity Class
public class MainActivity extends AppCompatActivity {
static TextView TvText;
Button Btn11, Btn22;
AlarmManager alarm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
TvText = (TextView) findViewById(R.id.tv_Text);
Btn11 = (Button) findViewById(R.id.btn_11);
Btn22 = (Button) findViewById(R.id.btn_22);
Btn22.setEnabled(false);
}
public void Btn11OC(View view) {
scheduleAlarm();
Btn11.setEnabled(false);
Btn22.setEnabled(true);
}
public void Btn22OC(View view) {
if (alarm!= null) {
cancelAlarm();
}
Btn11.setEnabled(true);
Btn22.setEnabled(false);
}
// Setup a recurring alarm every half hour
public void scheduleAlarm() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), broadtest.class);
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, broadtest.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 5 seconds
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(),
900000L, pIntent);
}
public void cancelAlarm() {
Intent intent = new Intent(getApplicationContext(), broadtest.class);
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
final PendingIntent pIntent = PendingIntent.getBroadcast(this, broadtest.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarm.cancel(pIntent);
}
}
Broad Cast Receiver
public class broadtest extends WakefulBroadcastReceiver {
public static final int REQUEST_CODE = 12345;
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MyService.class);
context.startService(i);
}
}
AppController Class
public class AppController extends Application {
#Override
public void onCreate() {
super.onCreate();
}
}
MyService class
public class MyService extends IntentService {
static int NOTIFICATION_ID = 0;
public MyService() {
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
String url = "http://test.com/testts.php";
// Tag used to cancel the request
String tag_string_req = "string_req";
StringRequest strReq = new StringRequest(Request.Method.GET,
url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("Volley Log", response);
Toast.makeText(MyService.this, response, Toast.LENGTH_SHORT).show();
if (response.equals("0")){
sendNotification("Titel Test 1111", "Body Test 1111");
}else if (response.equals("1")){
sendNotification("Titel Test 2222", "Body Test 2222");
}else {
sendNotification("Titel Test 3333", "Body Test 3333");
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MyService.this, error.toString(), Toast.LENGTH_SHORT).show();
VolleyLog.d("Volley Log", "Error: " + error.getMessage());
}
});
// Adding request to request queue
int socketTimeout = 30000;//30 seconds - change to what you want
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
strReq.setRetryPolicy(policy);
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
// Setup periodic alarm every 5 seconds
}
private void sendNotification(String title, String messageBody) {
long[] pattern = {500,500,500,500,500,500,500,500,500};
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(alarmSound)
.setLights(Color.BLUE, 500, 500)
.setVibrate(pattern);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (NOTIFICATION_ID > 1073741824) {
NOTIFICATION_ID = 0;
}
notificationManager.notify(NOTIFICATION_ID++, notificationBuilder.build());
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gih.testmass">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".AppController"
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=".broadtest"
android:process=":remote">
</receiver>
<service
android:name=".MyService"
android:exported="false">
</service>
</application>
You need to start the service as a foreground service. When you clear app from recents it kills the service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_notification)
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(),
R.mipmap.ic_launcher))
.setContentTitle("WhatsApp Reminder Service.")
.setContentText("Touch to configure.");
Intent startIntent = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 965778, startIntent, 0);
builder.setContentIntent(pendingIntent);
startForeground(965778, builder.build());
return START_REDELIVER_INTENT;
}
It is necessary to build a notification when you use foreground service.
Hope it helps.
I see you have used IntentService
see answer to this question
Using startForeground() with an Intent Service
To run a process on a device when users are not particularly interacting with your application.
The steps will involve:
1.Updating your android manifest xml
2.Setting up broadcast receivers to listen to relevant events
3.Set up a background service for context when your application isn’t running
Android menifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission ... />
<application
android:name=".MyApplication"
... >
<receiver android:name=".receivers.PeriodicTaskReceiver">
<intent-filter>
<action android:name="com.example.app.PERIODIC_TASK_HEART_BEAT" />
</intent-filter>
</receiver>
<service android:name=".services.BackgroundService" />
...
</application>
Now for the Broadcast receiver
public class PeriodicTaskReceiver extends BroadcastReceiver {
private static final String TAG = "PeriodicTaskReceiver";
private static final String INTENT_ACTION = "com.example.app.PERIODIC_TASK_HEART_BEAT";
#Override
public void onReceive(Context context, Intent intent) {
if (!Strings.isNullOrEmpty(intent.getAction())) {
MyApplication myApplication = (MyApplication) context.getApplicationContext();
SharedPreferences sharedPreferences = myApplication.getSharedPreferences();
if (intent.getAction().equals("android.intent.action.BATTERY_LOW")) {
sharedPreferences.edit().putBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, false).apply();
stopPeriodicTaskHeartBeat(context);
} else if (intent.getAction().equals("android.intent.action.BATTERY_OKAY")) {
sharedPreferences.edit().putBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, true).apply();
restartPeriodicTaskHeartBeat(context, myApplication);
} else if (intent.getAction().equals(INTENT_ACTION)) {
doPeriodicTask(context, myApplication);
}
}
}
private void doPeriodicTask(Context context, MyApplication myApplication) {
// Periodic task(s) go here ...
}
public void restartPeriodicTaskHeartBeat(Context context, MyApplication myApplication) {
SharedPreferences sharedPreferences = myApplication.getSharedPreferences();
boolean isBatteryOk = sharedPreferences.getBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, true);
Intent alarmIntent = new Intent(context, PeriodicTaskReceiver.class);
boolean isAlarmUp = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_NO_CREATE) != null;
if (isBatteryOk && !isAlarmUp) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmIntent.setAction(INTENT_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);
}
}
public void stopPeriodicTaskHeartBeat(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(context, PeriodicTaskReceiver.class);
alarmIntent.setAction(INTENT_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
alarmManager.cancel(pendingIntent);
}
}
here com.example.app.PERIODIC_TASK_HEART_BEAT is application’s own broadcast, created and sent from our restartPeriodicTaskHeartBeat method.
your Alarmmanager should have this line
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);
Now for your background service class:
public class BackgroundService extends Service {
private static final String TAG = "BackgroundService";
PeriodicTaskReceiver mPeriodicTaskReceiver = new PeriodicTaskReceiver();
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyApplication myApplication = (MyApplication) getApplicationContext();
SharedPreferences sharedPreferences = myApplication.getSharedPreferences();
IntentFilter batteryStatusIntentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatusIntent = registerReceiver(null, batteryStatusIntentFilter);
if (batteryStatusIntent != null) {
int level = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPercentage = level / (float) scale;
float lowBatteryPercentageLevel = 0.14f;
try {
int lowBatteryLevel = Resources.getSystem().getInteger(Resources.getSystem().getIdentifier("config_lowBatteryWarningLevel", "integer", "android"));
lowBatteryPercentageLevel = lowBatteryLevel / (float) scale;
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Missing low battery threshold resource");
}
sharedPreferences.edit().putBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, batteryPercentage >= lowBatteryPercentageLevel).apply();
} else {
sharedPreferences.edit().putBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, true).apply();
}
mPeriodicTaskReceiver.restartPeriodicTaskHeartBeat(BackgroundService.this);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
startSelf();
}
}
Here the Backgroundservice tries to find the device’s low battery threshold and set our battery control flag appropriately before it attempts to restart the Broadcast receiver.
And START_STICKY will try to re-create your service after it is killed and call onStartCommand() again with a null intent.
Finally for your Application class start the Background service:
public class MyApplication extends Application {
private static final String TAG = "MyApplication";
#Override
public void onCreate() {
super.onCreate();
// Initialize the singletons so their instances
// are bound to the application process.
...
Intent startServiceIntent = new Intent(context, BackgroundService.class);
startService(startServiceIntent);
}
}
For detail implementation see this:https://technology.jana.com/2014/10/28/periodic-background-tasks-in-android/
be sure to make you service like this in your Mainifest
<service
android:name=".service.youservice"
android:exported="true"
android:process=":ServiceProcess" />
then your service will run on other process named ServiceProcess
if you want make your service never die :
onStartCommand() return START_STICKY
onDestroy() -> call startself
if nothing works use startForeground() service..
I want notification when reboot android mobile phone. But when run application notification show. i Implement all permission. so please anyone help me. I am struck for three day. Please help me.
public class BeaconService extends Service {
public BeaconService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
showNotification()
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
Log.v(TAG, "service destroyed");
}
private void showNotification() {
NotificationCompat.Builder mBuilder =
(NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_loc)
.setContentTitle("Welcome to Ford Show Room")
.setContentText("Hello Puneet, Welcome to Ford! You'll be shortly attended by Karthik! ")
.setPriority(2)
.setOnlyAlertOnce(false);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mBuilder.setSound(alarmSound);
Intent resultIntent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(2001, mBuilder.build());
}
}
AutoBeaconNotifyReceiver.java
public class AutoBeaconNotifyReceiver extends BroadcastReceiver {
private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(BOOT_COMPLETED_ACTION)) {
Intent myIntent = new Intent(context, BeaconService.class);
context.startService(myIntent);
}
}
menifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<service android:name="com.kontakt.sdk.android.ble.service.ProximityService" android:exported="false"/>
<receiver android:name=".AutoBeaconNotifyReceiver" android:label="BeaconNotifyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
What I am trying to do here is to raised a notification after a certain time by using BroadcastReceiver.With the following set of code i am able to achieve that also. But I want even the application is closed it will raised the notification.
MainActivity.java
public class MainActivity extends Activity {
IntentFilter ii;
TimeReciever tr;
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ii=new IntentFilter("android.intent.action.TIME_TICK");
tr=new TimeReciever();
registerReceiver(tr, ii);
}
}
=================================
TimeReciever.java
public class TimeReciever extends BroadcastReceiver{
int a=0;
public void onReceive(Context ctx, Intent in) {
System.out.println("On reciever");
a+=a;
a++;
System.out.println("value of a="+a);
if(a==31){
Toast.makeText(ctx,"Reciver Executed ", 40).show();
showNotification(ctx);
}
}
private void showNotification(Context context) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Log Reminder")
.setContentText("It's time to log the Breakfast !");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, MainActivity.class);
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(1, mBuilder.build());
a=0;
}
}
===============================
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.notificationbybroadcastre"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name="com.example.notificationbybroadcastre.TimeReciever">
<intent-filter>
<action android:name="android.intent.action.TIME_TICK"/>
</intent-filter>
</receiver>
<activity
android:name="com.example.notificationbybroadcastre.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>
Here The Answer.I have done It Through AlaramManager.
Main Activity
===============
public class MainActivity extends Activity
{
private PendingIntent pendingIntent;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent,0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 480, pendingIntent);
} //end onCreate
}
================================================================
MyAlarmService.java
================================
public class MyAlarmService extends Service
{
private NotificationManager mManager;
#Override
public IBinder onBind(Intent arg0)
{
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate()
{
// TODO Auto-generated method stub
super.onCreate();
}
#SuppressWarnings("static-access")
#Override
public void onStart(Intent intent, int startId)
{
showNotification(this);
}
private void showNotification(Context context) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Meal Log Reminder")
.setContentText("It's time to log Your Meal!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, MainActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setDefaults(Notification.DEFAULT_ALL);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(1, mBuilder.build());
}
#Override
public void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
}
}
===================================================
MyReceiver.java
=========================
public class MyReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Intent service1 = new Intent(context, MyAlarmService.class);
context.startService(service1);
}
}