Today I started writing for android. I want a simple (I think) app that waits for notification with specified title and then does something. I tried this code for service
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Toast;
public class NotificationListener extends NotificationListenerService {
Context context;
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onCreate() {
Toast.makeText(this, "onCreate", Toast.LENGTH_LONG).show();
super.onCreate();
context = getApplicationContext();
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
Toast.makeText(this,"NOTIFICATION",Toast.LENGTH_SHORT).show();
String text = "";
String title = "";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
Bundle extras = extras = sbn.getNotification().extras;
text = extras.getCharSequence("android.text").toString();
title = extras.getString("android.title");
}
Log.i("Package",pack);
Log.i("Title",title);
Log.i("Text",text);
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Toast.makeText(this,"NOTIFICATION removed",Toast.LENGTH_SHORT).show();
Log.i("Msg","Notification was removed");
}
}
Then added this to manifest:
<service
android:name=".NotificationListener"
android:enabled="true"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
finally started the service in MainActivity onCreate() startService(new Intent(context, NotificationListener.class));
onNotificationPosted does not work. It seems like service was started correctly, because toasts from onStartCommand and onCreate were shown. I tried on emulator and real device. I also allowed notification access in settings. Please help, I wasted 5 hours on that.
Related
In my app(java) I am getting values from two different crypto Exchange. Then doing some calculation and getting output values. Values are refreshing every second. Now I want to set alert/notification whenever output values is greater than specific value. I want this whenever app is closed or running. How to do that because I am not able to do that when app is closed? Thanks.
You have to use Foreground Service to enable notification even when app is closed .
According to AndroidDevelopers,
Foreground services perform operations that are noticeable to the
user. Each foreground service must show a status bar notification that
has a priority of PRIORITY_LOW or higher. That way, users are actively
aware that your app is performing a task in the foreground and is
consuming system resources.
https://developer.android.com/guide/components/foreground-services
Example of code from Programmer'sWorld, to create foreground services and notification in your Android App
package com.example.myserviceclass;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class MyService extends Service {
private Integer alarmHour;
private Integer alarmMinute;
private Ringtone ringtone;
private Timer t = new Timer();
private static final String CHANNEL_ID = “MyNotificationChannelID”;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
alarmHour = intent.getIntExtra(“alarmHour”, 0);
alarmMinute = intent.getIntExtra(“alarmMinute”, 0);
ringtone = RingtoneManager.getRingtone(getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
try {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID )
.setContentTitle(“My Alarm clock”)
.setContentText(“Alarm time – ” + alarmHour.toString() + ” : ” + alarmMinute.toString())
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, “My Alarm clock Service”, NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
}
catch (Exception e){
e.printStackTrace();
}
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (Calendar.getInstance().getTime().getHours() == alarmHour &&
Calendar.getInstance().getTime().getMinutes() == alarmMinute){
ringtone.play();
}
else {
ringtone.stop();
}
}
}, 0, 2000);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
ringtone.stop();
t.cancel();
super.onDestroy();
}
}
package com.example.myserviceclass;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.TimePicker;
public class MainActivity extends AppCompatActivity {
private TimePicker timePicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.FOREGROUND_SERVICE}, PackageManager.PERMISSION_GRANTED);
timePicker = findViewById(R.id.timPicker);
final Intent intent = new Intent(this, MyService.class);
ServiceCaller(intent);
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker timePicker, int i, int i1) {
ServiceCaller(intent);
}
});
}
private void ServiceCaller(Intent intent){
stopService(intent);
Integer alarmHour = timePicker.getCurrentHour();
Integer alarmMinute = timePicker.getCurrentMinute();
intent.putExtra(“alarmHour”, alarmHour);
intent.putExtra(“alarmMinute”, alarmMinute);
startService(intent);
}
}
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package=”com.example.myserviceclass”>
<uses-permission android:name=”android.permission.FOREGROUND_SERVICE”/>
<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=”.MyService”/>
<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>
You can do with Notification setting.
first go in setting,
then in notification setting ,
on notification for your app.
Thank you
For this purpose, you can create a foreground service running. This way, you'll be able to notify the user even after he has exited out from the App.
Reference : https://developer.android.com/guide/components/foreground-services?authuser=1
I've been playing around with some Android recently and have the following setup:
I have app A, which is a service. This has no activity. Here's its manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sandbox.sampleservice">
<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/Theme.SampleService">
<service
android:name=".DummyService"
android:exported="true"
android:enabled="true">
</service>
</application>
</manifest>
and here's the Java code:
package com.sandbox.sampleservice;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
public class DummyService extends Service {
private static final String TAG = "DummyService";
static class MessageHandler extends Handler {
#Override
public void handleMessage(Message msg) {
// TODO: sort this later
super.handleMessage(msg);
}
}
Messenger mMessenger = null;
#Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "Binding");
mMessenger = new Messenger(new MessageHandler());
return mMessenger.getBinder();
}
#Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "No longer bound");
return false;
}
}
I then have an app B with an empty activity which I want to bind to the service in app A. This is it's MainActivity:
package com.sandbox.sampleclient;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "SampleClient";
private ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "Bound");
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "Unbound");
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.sandbox.sampleservice", ".DummyService"));
boolean result = this.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
if (result) {
Toast.makeText(this, "success", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "failed", Toast.LENGTH_SHORT).show();
}
}
}
I'm running on the default emulator that comes with Android Studio - API 30/x86.
I've installed the service using the installDebug Gradle task and can see the app in the Settings. But running app B, the call to bindService() returns false (it shows the failure toast). And I have the following message in logcat:
2021-04-03 20:33:59.743 500-1764/system_process W/ActivityManager: Unable to start service Intent { cmp=com.sandbox.sampleservice/.DummyService } U=0: not found
I've tried a few things - using the app context rather than the activity one when binding, using the fully qualified class name, and more. No change in behaviour, and the error in logcat is always the same.
I am trying to send an explicit broadcast to a receiver that's dynamically registered inside an activity but it doesn't seem to work. I've tried adding the action that the intent filter is expecting but that doesn't work either. Only when I use a public implicit intent it picks up the broadcast.
Could any one tell me why? The code is for Android 8.0+ and I have marked the line inside CustomReceiver.
In summary it should...
Service starts, dynamically registers a CustomReceiver to listen for a implicit broadcast.
CustomReceiver receives implicit broadcast, tries to send explicit broadcast to MainActivity.
MainActivity receiver catches the explicit broadcast and does something.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.demos.democode">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".CustomService" />
</application>
</manifest>
MainActivity.java
package com.demos.democode;
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter(CustomService.customActionActivity);
getApplicationContext().registerReceiver(activityReceiver, intentFilter);
Intent serviceIntent = new Intent(this,CustomService.class);
this.startForegroundService(serviceIntent);
Log.d("DEMO_APP", "create");
}
BroadcastReceiver activityReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("DEMO_APP", "activity receiver");
}
};
}
CustomReceiver.java - Explicit broadcast from here doesn't work.
package com.demos.democode;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class CustomReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("DEMO_APP", "custom receiver");
// DOESN'T WORK! this explicit broadcast doesn't work even after setting an action in - why?
Intent i = new Intent(context, MainActivity.class);
i.setAction(CustomService.customActionActivity);
context.sendBroadcast(i);
// this implicit public broadcast works fine
i = new Intent(CustomService.customActionActivity);
context.sendBroadcast(i);
}
}
CustomService.java
package com.demos.democode;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
public class CustomService extends Service {
protected Context context = null;
public static String customAction = "EVENT_1";
public static String customActionActivity = "EVENT_2";
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
NotificationChannel serviceChannel = new NotificationChannel(
"DEMO_CHANNEL",
"Demo App",
NotificationManager.IMPORTANCE_LOW
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
Notification notification = new NotificationCompat.Builder(context, "DEMO_CHANNEL")
.setSmallIcon(R.drawable.ic_launcher_foreground)
//.setContentText("Total screen time today: " + totalTimeDisplay )
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(1, notification);
startForeground(1, notification);
IntentFilter intentFilter = new IntentFilter(customAction);
CustomReceiver customReceiver = new CustomReceiver();
context.registerReceiver( customReceiver , intentFilter);
Log.d("DEMO_APP", "service created");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final Intent i = new Intent(customAction);
Log.d("DEMO_APP", "service started");
sendBroadcast(i);
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
You are trying to launch an Activity using sendBroadcast()
In this code:
// DOESN'T WORK! this explicit broadcast doesn't work even after setting an action in - why?
Intent i = new Intent(context, MainActivity.class);
i.setAction(CustomService.customActionActivity);
context.sendBroadcast(i);
You are trying to launch an Activity, so the last line needs to be:
content.startActivity(i);
Sorry I am rather late to the party, but I think the error is in registration of receiver in the MainActivity. You have used
getApplicationContext().registerReceiver(activityReceiver, intentFilter);
Which is using application context to register receiver.
It should be replaced by:
registerReceiver(activityReceiver, intentFilter);
In which the receiver will be registered for that specific activity instance of Context.
I would like to provide a service that can be called by other app. Therefore, I have a service and an aidl. But when I try to have a separate application to bind this service (bindService), it just returns me false which means fail. Here is my code.
I'm using the code from books Pro Android 2
I've already tried many solutions in other questions similar to this, but there isn't any working solution for me.
I've tried fix the aidl intent filter but it's still not working
I've tried fix the package name and class name in client app, but it's still not working.
Please help me!
On Client :
// IStockQuoteService.aidl
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;
// Declare any non-default types here with import statements
interface IStockQuoteService {
double getQuote(String ticker);
}
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteclient;
import id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice.IStockQuoteService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
protected static final String TAG = "StockQuoteClient";
private IStockQuoteService stockService = null;
private Button bindBtn;
private Button callBtn;
private Button unbindBtn;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindBtn = (Button)findViewById(R.id.bindBtn);
bindBtn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
".ahmad_fauzan_amirul_isnain.stockquoteservice",
"com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
".stockquoteservice.IStockQuoteService");
Log.d("Hasil", String.valueOf(bindService(intent,
serConn, Context.BIND_AUTO_CREATE)));
bindBtn.setEnabled(false);
callBtn.setEnabled(true);
unbindBtn.setEnabled(true);
}});
callBtn = (Button)findViewById(R.id.callBtn);
callBtn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view) {
callService();
}});
callBtn.setEnabled(false);
unbindBtn = (Button)findViewById(R.id.unbindBtn);
unbindBtn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view) {
unbindService(serConn);
bindBtn.setEnabled(true);
callBtn.setEnabled(false);
unbindBtn.setEnabled(false);
}});
unbindBtn.setEnabled(false);
}
private void callService() {
try {
double val = stockService.getQuote("SYH");
Toast.makeText(MainActivity.this, "Value from service is "+val,
Toast.LENGTH_SHORT).show();
} catch (RemoteException ee) {
Log.e("MainActivity", ee.getMessage(), ee);
}
}
private ServiceConnection serConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service)
{
Log.v(TAG, "onServiceConnected() called");
stockService = IStockQuoteService.Stub.asInterface(service);
callService();
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.v(TAG, "onServiceDisconnected() called");
stockService = null;
}
};
}
On Service :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="StockQuoteService">
<intent-filter>
<action android:name="com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice.IStockQuoteService"
/>
</intent-filter>
</service>
</application>
</manifest>
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class StockQuoteService extends Service
{
private static final String TAG = "StockQuoteService";
public class StockQuoteServiceImpl extends IStockQuoteService.Stub
{
#Override
public double getQuote(String ticker) throws RemoteException
{
Log.v(TAG, "getQuote() called for " + ticker);
return 20.0;
}
}
#Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "onCreate() called");
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.v(TAG, "onDestroy() called");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.v(TAG, "onStart() called");
}
#Override
public IBinder onBind(Intent intent)
{
Log.v(TAG, "onBind() called");
return new StockQuoteServiceImpl();
}
}
// IStockQuoteService.aidl
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;
// Declare any non-default types here with import statements
interface IStockQuoteService {
double getQuote(String ticker);
}
I'm using the code from books Pro Android 2
That book is from 2010. Much of that book will be out of date. Please use something newer. If nothing else, you can download older editions of one of my books for free. Right now, the most recent version of those is from 2015 — while that too is a bit old, it is much more up to date than a book from 2010.
I've already tried many solutions in other questions similar to this, but there isn't any working solution for me.
You have:
intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
".ahmad_fauzan_amirul_isnain.stockquoteservice",
"com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
".stockquoteservice.IStockQuoteService");
The package in your manifest has id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice. Assuming that your applicationId in your module's build.gradle file is the same, I think that this matches what you have in your code. Your application ID is very long — in the future, I recommend that you use something shorter and easier to visually compare.
However, your class name is wrong. Your <service> class is StockQuoteService, not IStockQuoteService. IStockQuoteService is the name of the AIDL, not the service, and your Intent needs to point to the service. So, try:
intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
".ahmad_fauzan_amirul_isnain.stockquoteservice",
"com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
".stockquoteservice.StockQuoteService");
Or, to reduce duplication:
String packageName = "com.id.ac.ui.cs.mobileprogramming" +
".ahmad_fauzan_amirul_isnain.stockquoteservice";
intent.setClassName(packageName, packageName+".StockQuoteService");
My task is to run service even if app is closed.
My service class:
public class MyService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
AudioManager am;
am= (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
if(am.getRingerMode() == AudioManager.RINGER_MODE_NORMAL)
am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
else
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
Minute minute = new Minute();
Calendar cal = Calendar.getInstance();
AlarmManager alarms ;
Intent activate = new Intent(this, MyService.class);
PendingIntent alarmIntent = PendingIntent.getService(this, 0, activate, 0);
alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
cal.set(Calendar.HOUR_OF_DAY, 00);
cal.set(Calendar.MINUTE, minute.minute);
cal.set(Calendar.SECOND, 00);
alarms.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmIntent);
Toast.makeText(this, "checkOnStart", Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}
}
In my activity:
Intent activate = new Intent(this, MyService.class);
startService(activate);
But when I kill the app the service closed, what should I do to keep the service running after the app is killed?
It could be achieve by calling the service itself when it will be killed. But I can't really sure about it because I never trying it.
This article could be a help:
Creating an never ending background service in android
Read the similar question and answers at Android Service need to run always(Never pause or stop)
-- Edited --
Here to near complete implementation from the article:
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="oak.shef.ac.uk.testrunningservicesbackgroundrelaunched">
<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>
<service
android:name="oak.shef.ac.uk.testrunningservicesbackgroundrelaunched.SensorService"
android:enabled="true" >
</service>
<receiver
android:name="oak.shef.ac.uk.testrunningservicesbackgroundrelaunched.SensorRestarterBroadcastReceiver"
android:enabled="true"
android:exported="true"
android:label="RestartServiceWhenStopped">
<intent-filter>
<action android:name="uk.ac.shef.oak.ActivityRecognition.RestartSensor"/>
</intent-filter>
</receiver>
</application>
</manifest>
MainActivity
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
Intent mServiceIntent;
private SensorService mSensorService;
Context ctx;
public Context getCtx() {
return ctx;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
setContentView(R.layout.activity_main);
mSensorService = new SensorService(getCtx());
mServiceIntent = new Intent(getCtx(), mSensorService.getClass());
if (!isMyServiceRunning(mSensorService.getClass())) {
startService(mServiceIntent);
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.i ("isMyServiceRunning?", true+"");
return true;
}
}
Log.i ("isMyServiceRunning?", false+"");
return false;
}
#Override
protected void onDestroy() {
stopService(mServiceIntent);
Log.i("MAINACT", "onDestroy!");
super.onDestroy();
}
}
Service
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by fabio on 30/01/2016.
*/
public class SensorService extends Service {
public int counter=0;
public SensorService(Context applicationContext) {
super();
Log.i("HERE", "here I am!");
}
public SensorService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
Intent broadcastIntent = new Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
stoptimertask();
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 1000, 1000); //
}
/**
* it sets the timer to print the counter every x seconds
*/
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
Log.i("in timer", "in timer ++++ "+ (counter++));
}
};
}
/**
* not needed
*/
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Service Restarter
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class SensorRestarterBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(SensorRestarterBroadcastReceiver.class.getSimpleName(), "Service Stops! Oooooooooooooppppssssss!!!!");
context.startService(new Intent(context, SensorService.class));;
}
}
The service sends a message to the BroadcastReceiver which will restart the service after the service stop (it is an asynchronous call so it will not be affected by the death of the service.
The complete source code is here