To save battery in my app I decided to use the "new" Fused locations. However I need to pass some parameters into the service which receives GPS updates. The way It's done below would work (putExtras(...)), but I would need to make a lot of classes Serializable/Parseable, which would be a pain.
I have searched around and found some other way using Binder, but can't figure out how to get it to work. Is using Binder the only way or is there another?
If anything is unclear, please tell.
Thank you.
public class LocationService extends IntentService {
...
public LocationService(StartActivity startActivity, DatabaseSQLite db, HomeFragment homeFragment) {
super("Fused Location Service");
...
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
db = (DatabaseSQLite) intent.getExtras().get("DatabaseSQLite");
...
return START_REDELIVER_INTENT;
}
}
And this is how It's used in my activity:
#Override
public void onConnected(Bundle bundle) {
mIntentService = new Intent(this, LocationService.class);
mIntentService.putExtra("DatabaseSQLite", database);
...
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);
}
You should check out https://github.com/greenrobot/EventBus
Examples can be found here: http://awalkingcity.com/blog/2013/02/26/productive-android-eventbus/
Basically lets you do stuff like:
#Override
public void onConnected(Bundle bundle) {
mIntentService = new Intent(this, LocationService.class);
// could be any object
EventBus.getDefault().postSticky(database);
...
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);
}
And whenever you need the object
public class LocationService extends IntentService {
...
public LocationService(StartActivity startActivity, DatabaseSQLite db, HomeFragment homeFragment) {
super("Fused Location Service");
...
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// could also be in Broadcast Receiver etc..
db = EventBus.getDefault().getStickyEvent(DatabaseSQLite.class);
...
return START_REDELIVER_INTENT;
}
}
Not only is it simpler, this link also shows that it outperforms other methods: http://www.stevenmarkford.com/passing-objects-between-android-activities/
Related
I am developing android application, so I am starting a service with alarm:
public void scheduleLocationCheckerAlarm() {
Intent intent = new Intent(getApplicationContext(), LocationCheckerReceiver.class);
final PendingIntent pIntent = PendingIntent.getBroadcast(this, LocationCheckerReceiver.REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
long firstMillis = System.currentTimeMillis();
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, 600000, pIntent);
}
LocationCheckerReceiver:
public class LocationCheckerReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, LocationNotificator.class);
context.startService(i);
}
Service:
public class LocationNotificator extends Service {
public LocationNotificator() {
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("Location checker", "Service running");
//My code is here
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("Location checker", "Service destroyed");
}
So I want this service to be checking for something every 1 minute and to be running all the time, even when the application is closed by the user.
You must call startForeground(FOREGROUND_ID, buildForegroundNotification(filename)); in order to ensure that your service running continuously. Also, this will post a notification from your app to show the user about the service state. Please follow the reference.
Here is the code :
public class LocationNotificator extends Service {
private static int FOREGROUND_ID=1338;
public LocationNotificator() {
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("Location checker", "Service running");
//My code is here
startForeground(FOREGROUND_ID,
buildForegroundNotification(filename));
stopForeground(true);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("Location checker", "Service destroyed");
}
private Notification buildForegroundNotification(String filename) {
NotificationCompat.Builder b=new NotificationCompat.Builder(this);
b.setOngoing(true);
b.setContentTitle("Some Title")
.setContentText("some File name")
.setSmallIcon(android.R.drawable.stat_sys_download)
.setTicker("downloading");
return(b.build());
}
You need to read this first. https://developer.android.com/guide/components/services.html
In a nutshell, start your service as a foreground service so there's lesser chance of Android killing your service. As a foreground service, you need to display an on-going notification in the status bar.
There's no direct way of making sure your service is never killed by the Android system. A workaround is to send a broadcast in onDestroy() of your service, and have a Receiver in your Android application start the service upon receiving the broadcast.
By the way, it seems that your service is sending location updates periodically to your backend server. This might be better implemented using Firebase Job Dispatcher library or Evernote's Android-Job library.
The service works normally when is started from the MainActivity however when the application is removed from the recent apps or when activity is closed, the service is restarted instead of continuing from where it left off.
public class ServiceExample extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO: Implement this method
return null;
}
#Override
public void onCreate() {
// TODO: Implement this method
super.onCreate();
//Do Something
}
I need to perform an action in the background but it can not be stopped or restarted when the activity ends. The Service Statement is the best to Use?
Try putting this inside your service class.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
Add below code to service and override onStartCommand and return START_STICKY
#Override
public void onTaskRemoved(Intent rootIntent){
Intent restartServiceTask = new Intent(getApplicationContext(),this.getClass());
restartServiceTask.setPackage(getPackageName());
PendingIntent restartPendingIntent = PendingIntent.getService(getApplicationContext(), 1,restartServiceTask, PendingIntent.FLAG_ONE_SHOT);
AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
myAlarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartPendingIntent
);
super.onTaskRemoved(rootIntent);
}
I have a service and application. There is communication between them by sending intents on specific situations. In activity I register and unregister broadcast receiver to collect this intents. Intents from service are sending when particular callback method is executed. Is there a possibility to send this intents only when activity is in the foreground? Because when this is hide there is no need to gather this intents (it helpful only to show some situations in real time)? I figure out that in activity could be static field that indicates about such situation, but I don't know how to get access to activity from service and additionally I found information that this is vary bad design practise.. Thank for any suggestions!
Declare this in your Activity:
public static boolean isRunning;
Then in your onPause to set isRunning = false;
and in onResume set it to isRunning = true;
Then from your Service you can simply call ActivityName.isRunning to know if it is in foreground or not!
you can use a static variable within the activity.
class MyActivity extends Activity {
static boolean active = false;
#Override
public void onStart() {
super.onStart();
active = true;
}
#Override
public void onStop() {
super.onStop();
active = false;
}
}
Add just check in service as
if(MyActivity.active)
{
//send broadcast.
}
OR
go with this to check status of activity is it active or not
public boolean isRunning(Context ctx) {
ActivityManager activityManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (RunningTaskInfo task : tasks) {
if (ctx.getPackageName().equalsIgnoreCase(task.baseActivity.getPackageName()))
return true;
}
return false;
}
I'd have a local boolean variable in service:
protected boolean mIsAppRunning;
Call startService() with true/false extra when app resumes/stops:
#Override
protected void onResume() {
super.onResume();
Intent service = new Intent("my.service.ACTION");
service.putExtra("IS_MY_ACTIVITY_RUNNING", true);
startService(service);
}
#Override
protected void onPause() {
Intent service = new Intent("my.service.ACTION");
service.putExtra("IS_MY_ACTIVITY_RUNNING", false);
startService(service);
}
Check that extra in service's onStartCommand() and assign its value to mIsAppRunning:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
mIsAppRunning = intent.getBooleanExtra("IS_MY_ACTIVITY_RUNNING", false);
}
return START_STICKY;
}
If you design the logic in the service a little carefully, you may even get rid of the local variable, mIsAppRunning, and call the required methods depending on the intent extra value.
Hope this helps.
i need a service in my app that starts first time and runs forever, even if user restart his phone, my service starts automatically without running my app. i write this code but when user restart his phone, my service doesn't start again!!
public class notifService extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStart(intent, startId);
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
and in the main activity i start service like this:
// start service
Intent service = new Intent(MainActivity.this, notifService.class);
MainActivity.this.startService(service);
thanks for you help.
Listen for android.intent.action.BOOT_COMPLETED in BroadcastReceiver and start your service.
For example
public class YourDefinedBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, notifService.class);
context.startService(service);
}
}
Also, you must hold the permission:
RECEIVE_BOOT_COMPLETED
Ref: Automatically starting Services in Android after booting and Android Start Service on Boot Automatically
It's code here:
public class MyServeice extends Service
{
private Timer pushTimer;
private final int NOTEF_ID = 1234;
NotificationManager manager;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
Log.i("MyActivity", "1");
//pushTimer = new Timer();
manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
}
#Override
public void onDestroy()
{
Log.i("MyActivity", "2");
//pushTimer.cancel();
}
#Override
public void onStart(Intent intent, int startid)
{
Log.i("MyActivity", "3");
//pushTimer.schedule(new TimerTask()
//{
// #Override
// public void run()
// {
Notification not = new Notification(R.drawable.ic_launcher, "Custom notification", System.currentTimeMillis());
PendingIntent notIntent = PendingIntent.getActivity(this , 0, new Intent(this, MainActivity.class), 0);
not.setLatestEventInfo(this, "Title", "Text", notIntent);
manager.notify(NOTEF_ID, not);
manager.cancel(NOTEF_ID);
// }
//}, 0L, 60L * 1000);
}
}
I try to start it from my MainActivity activity class (before I thought that problem is in timer, but now I comment it).
Starting code here:
startService(new Intent(this, MyServeice.class));
Log from Service class is not shown, so I decided that Service is not started at all. Application doesn't crash and started normaly. Can you check my code?
You made a mistake in MyServeice Class
You use
#Override
public void onStart(Intent intent, int startid)
& in Service Life cycle there is no onStart(..) Method
Try this method instead of above
#Override
public int onStartCommand(Intent intent, int flags, int startId)
EDIT:
& second One you have to declare service in Manifest File Like:
<manifest ... >
...
<application ... >
<service android:name=".MyServeice" />
...
</application>
</manifest>
For more Information About Service Refer this Documentation
http://developer.android.com/guide/components/services.html
Use this method :
#Override
public int onStartCommand(Intent intent, int flags, int startId) {}
Here is good tutorial about services : Click here !
Question closed. Adding info about my service class into manifest solved my problem.