Service and Chronometer Synchronization - android

I need to be able to start chronometer, then close activity, after that through notifications, back to that activity, and see the right time in chronometer.
What I've Done
A part of my Activity:
public void doClick(View target)
{
switch(target.getId())
{
case R.id.buttonStart:
{
Mchronometer.setBase(SystemClock.elapsedRealtime());
Mchronometer.start();
Intent intent = new Intent(RecentActivity.this, ChronometerService.class);
intent.putExtra("task_name",task_name);
intent.putExtra("task_id",task_id);
intent.putExtra("ellapsedTime",Mchronometer.getBase());
Log.d("base",""+Mchronometer.getBase());
startService(intent);
break;
}
case R.id.buttonStop:
{
stopService(new Intent(RecentActivity.this, ChronometerService.class));
Mchronometer.stop();
Mchronometer.setBase(SystemClock.elapsedRealtime());
break;
}
case R.id.button3:
{
break;
}
}
}
A part of my Service:
public class ChronometerService extends Service {
private ThreadGroup myThreads = new ThreadGroup("ServiceWorker");
private NotificationManager notificationMgr;
private int task_id;
private long ellapsedTime;
#Override
public void onCreate() {
super.onCreate();
notificationMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
String task_name =intent.getExtras().getString("task_name");
task_id =intent.getExtras().getInt("task_id");
ellapsedTime = intent.getExtras().getLong("ellapsedTime");
Log.d("servicebase",""+ellapsedTime);
displayNotificationMessage(task_name);
new Thread(myThreads, new ServiceWorker(),"ChronometerService").start();
return START_STICKY;
}
private class ServiceWorker implements Runnable {
public void run() {
}
}
#Override
public void onDestroy()
{
myThreads.interrupt();
notificationMgr.cancelAll();
super.onDestroy();
}
public IBinder onBind(Intent intent) {
return null;
}
public void displayNotificationMessage(String message){
Notification notification = new Notification(R.drawable.emo_im_winking,message,System.currentTimeMillis());
notification.flags = Notification.FLAG_NO_CLEAR;
Intent intent = new Intent(this, RecentActivity.class);
intent.putExtra("task_id", task_id);
intent.putExtra("ellapsedTime",ellapsedTime);
Log.d("servicebase1",""+Long.toString(ellapsedTime));
PendingIntent contentintent = PendingIntent.getActivity(this,0,intent,0);
notification.setLatestEventInfo(this,"ChronometerService",message,contentintent);
notificationMgr.notify(0, notification);
}
}
I tried to send a message from activity to a service, which contains elapsed information.
If I started it first on my device (after system load) it's works right, but when I launch it again. The activity receives wrong message. It receives the time of the first service launched on the device.
As you can see I also send one more variable, and activity reads it correctly.

I've found a solution to my question.
It's simple.
It's needed to use flag(PendingIntent.FLAG_UPDATE_CURRENT)
PendingIntent contentintent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
And it's work fine.

Related

The same push notification keeps appearing whenever i open my apps

The same push notification keeps appearing whenever I reopen my apps although i have already cleared the notification in the notification bar. Secondly how do I implement a service so that my apps can receive notification although the apps is closed.
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences sharedPreferences = getSharedPreferences(Constants.SHARED_PREF, MODE_PRIVATE);
String id = sharedPreferences.getString(Constants.UNIQUE_ID, null);
Firebase firebase = new Firebase(Constants.FIREBASE_APP + id);
firebase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
String msg = snapshot.child("msg").getValue().toString();
if (msg.equals("none"))
return;
showNotification(msg);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("The read failed: ", firebaseError.getMessage());
}
});
return START_STICKY;
}
private void showNotification(String msg){
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
Intent intent = new Intent(NotificationListener.this,ViewRecord.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pendingIntent);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(alarmSound);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
builder.setContentTitle("Notifier");
builder.setContentText(msg);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
builder.setAutoCancel(true);
notificationManager.notify(1, builder.build());
}
my service code as below. and i call the service at onCreate function in the 1st activity..
public class MyService extends Service {
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
Toast.makeText(this, "The new Service was Created", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
// For time consuming an long tasks you can launch a new thread here...
Toast.makeText(this, " Service Started", Toast.LENGTH_LONG).show();
}
}
Posting this as answer since code in comment wud make it look unstructured
isServiceStarted
public class MainActivity extends AppCompatActivity {
private SharedPreferences servicePref;
private boolean isServiceStarted;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
servicePref = getSharedPreferences("servicePref", MODE_PRIVATE);
isServiceStarted = servicePref.getBoolean("isServiceStarted", false);
if (!isServiceStarted) {
startService(new Intent(this, MyService.class));
servicePref.edit().putBoolean("isServiceStarted",true).apply();
}
}
and in ur MyService.class inside onStop method do this without fail.
public class MyService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
// save value as false when service gets destroyed so as to start again when u open the app
getSharedPreferences("servicePref", MODE_PRIVATE).edit().putBoolean("isServiceStarted",false).apply();
}
}
override the onStartCommand() method and then return START_STICKY.

Broadcast receiver is not working when app on foreground or active

I am building app regarding battery indicator and i am using code from this post.
Getting battery status even when the application is closed
it is working fine when app is closed, but when an app is active or on foreground it did not work or did not send any broadcast.
This is main activity from i start service
public class Main extends Activity {
private MyService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (service == null) {
Intent i = new Intent(this, MyService.class);
startService(i);
}
finish();
}
}
Following is the service code.
public class MyService extends Service{
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand");
// do not receive all available system information (it is a filter!)
final IntentFilter battChangeFilter = new IntentFilter(
Intent.ACTION_BATTERY_CHANGED);
// register our receiver
this.registerReceiver(this.batteryChangeReceiver, battChangeFilter);
return super.onStartCommand(intent, flags, startId);
}
private final BroadcastReceiver batteryChangeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
checkBatteryLevel(intent);
}
};
private void checkBatteryLevel(Intent batteryChangeIntent) {
// some calculations
final int currLevel = batteryChangeIntent.getIntExtra(
BatteryManager.EXTRA_LEVEL, -1);
final int maxLevel = batteryChangeIntent.getIntExtra(
BatteryManager.EXTRA_SCALE, -1);
final int percentage = (int) Math.round((currLevel * 100.0) / maxLevel);
if(percentage==100)
{
Intent intent = new Intent(getBaseContext(), Last.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(intent);
}
// do not forget to unregister
unregisterReceiver(batteryChangeReceiver);
} }
And when following activity start i did not receive any broadcast.
public class Last extends Activity {
Button btnCancel;
Uri notification;
Ringtone r;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_last);
notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
btnCancel = (Button) findViewById(R.id.stopsound);
btnCancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
r.stop();
}
});
} }
As I understood,
when you start application in first time, you see nothing, just service is started and a broadcast receiver is registered. When battery level will be changed, the method checkBatteryLevel() is calling and the broadcast receiver will be unregistered. As result you have never received a new changing of battery level.

Service never gets garbage collected

My application has a button : "Foreground". By clicking on the foreground button, a notification appears attached to a foreground service (started at the time of click). Clicking on my notification is supposed to stop my service (with a PendingIntent) to be able to be garbage collected, however, this is not the case. Android Studio tells me, that there is a reference to my Service held by a NotificationManager. The weird thing is that it only happens if I click on my notification after I closed the main activity.
My service code:
public class TestService extends IntentService {
public static final String ACTION_GO_FOREGROUND = "GO_FOREGROUND";
public static final String ACTION_DESTROY = "DESTROY";
private NotificationManagerCompat notificationManager;
public TestService() {
super("Name");
}
#Override
public void onCreate() {
super.onCreate();
notificationManager = NotificationManagerCompat.from(this);
}
#Override
public void onDestroy() {
super.onDestroy();
notificationManager.cancelAll();
notificationManager = null;
}
#Override
protected void onHandleIntent(Intent intent) {
}
#Override
public int onStartCommand(Intent intent, int flags, final int startId) {
switch (intent.getAction()) {
case ACTION_GO_FOREGROUND:
fg();
break;
case ACTION_DESTROY:
destruct();
break;
}
return START_STICKY;
}
private void destruct() {
stopForeground(true);
stopSelf();
}
private void fg() {
Intent intent = new Intent(this, TestService.class);
intent.setAction(ACTION_DESTROY);
// Create the notification.
android.support.v7.app.NotificationCompat.Builder notificationBuilder = new android.support.v7.app.NotificationCompat.Builder(this);
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher);
notificationBuilder.setTicker("Ticker");
notificationBuilder.setContentTitle("Title");
notificationBuilder.setContentText("Content text");
notificationBuilder.setContentIntent(PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
startForeground(1, notificationBuilder.build());
}
I know the code is messy, but it's just a sample. So why is there a reference to my service, but only if you close the activity and try to destroy the service?
Try removing the code from OnDestroy -
notificationManager.cancelAll();
notificationManager = null;
and place it in destruct() before calling stopSelf()

Notification reappears after cancellation

I have a notification in my service which I cancel in my onDestroy. The notification immediately reappears after cancel code executes. Any clues?. I have tried all the flags combinations. No joy. Code edited for brevity is here.
public class downservice extends Service{
Notification notification;
RemoteViews contentView;
private static final int notifyid = 1;
Context context;
NotificationManager mNM;
PendingIntent cintent;
#Override
public void onCreate() {
String ns = Context.NOTIFICATION_SERVICE;
mNM = (NotificationManager)getSystemService(ns);
Intent noteintent = new Intent(this, configact.class);
cintent = PendingIntent.getActivity(this, 0, noteintent, 0);
contentView= new RemoteViews(getPackageName(), R.layout.notify);
Message msgtx=Message.obtain();
handler.sendMessage(msgtx);
}
private void showNotification(long[] data) {
notification= new Notification();
notification.contentIntent = cintent;
notification.icon=R.drawable.notify;
notification.iconLevel=x;
notification.flags|=Notification.FLAG_AUTO_CANCEL;
contentView.setImageViewResource(R.id.notifyimage, R.drawable.notifyimage);
contentView.setTextViewText(R.id.notifytext,text);
notification.contentView = contentView;
// We use a layout id because it is a unique number. We use it later to cancel.
mNM.notify(notifyid, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
mNM.cancel(notifyid);
}
private Handler handler=new Handler(){
#Override
public void handleMessage(Message msg){
Message msgtx=Message.obtain();
msgtx.arg1=1;
long [] data=getdata();
showNotification(data);
handler.sendMessageDelayed(msgtx, updaterate*1000);
}
};
The handler continues to execute even after service is destroyed and hence the notification which is in the handler loop reappears. I modified the code so that the handler loop does not continue after onDestroy(). I also implemented Handler.Callback since it is cleaner rather than the inline code.
#Override
public boolean handleMessage(Message arg0) {
switch(arg0.arg1){
case 1:
Message msgtx=Message.obtain();
msgtx.arg1=loopstatus;
long [] data=getdata();
showNotification(data);
handler.sendMessageDelayed(msgtx, updaterate*1000);
break;
case 2:
mNM.cancel(notifyid);
break;
default:
break;
}
return true;
}

Start service in Android

I want to call a service when a certain activity starts. So, here's the Service class:
public class UpdaterServiceManager extends Service {
private final int UPDATE_INTERVAL = 60 * 1000;
private Timer timer = new Timer();
private static final int NOTIFICATION_EX = 1;
private NotificationManager notificationManager;
public UpdaterServiceManager() {}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// Code to execute when the service is first created
}
#Override
public void onDestroy() {
if (timer != null) {
timer.cancel();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startid) {
notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
int icon = android.R.drawable.stat_notify_sync;
CharSequence tickerText = "Hello";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
Context context = getApplicationContext();
CharSequence contentTitle = "My notification";
CharSequence contentText = "Hello World!";
Intent notificationIntent = new Intent(this, Main.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText,
contentIntent);
notificationManager.notify(NOTIFICATION_EX, notification);
Toast.makeText(this, "Started!", Toast.LENGTH_LONG);
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Check if there are updates here and notify if true
}
}, 0, UPDATE_INTERVAL);
return START_STICKY;
}
private void stopService() {
if (timer != null) timer.cancel();
}
}
And here is how I call it:
Intent serviceIntent = new Intent();
serviceIntent.setAction("cidadaos.cidade.data.UpdaterServiceManager");
startService(serviceIntent);
The problem is that nothing happens. The above code block is called at the end of the activity's onCreate. I already debugged and no exception is thrown.
Any idea?
Probably you don't have the service in your manifest, or it does not have an <intent-filter> that matches your action. Examining LogCat (via adb logcat, DDMS, or the DDMS perspective in Eclipse) should turn up some warnings that may help.
More likely, you should start the service via:
startService(new Intent(this, UpdaterServiceManager.class));
startService(new Intent(this, MyService.class));
Just writing this line was not sufficient for me. Service still did not work. Everything had worked only after registering service at manifest
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
...
<service
android:name=".MyService"
android:label="My Service" >
</service>
</application>
Java code for start service:
Start service from Activity:
startService(new Intent(MyActivity.this, MyService.class));
Start service from Fragment:
getActivity().startService(new Intent(getActivity(), MyService.class));
MyService.java:
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
private static String TAG = "MyService";
private Handler handler;
private Runnable runnable;
private final int runTime = 5000;
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
handler.postDelayed(runnable, runTime);
}
};
handler.post(runnable);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
if (handler != null) {
handler.removeCallbacks(runnable);
}
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG, "onStart");
}
}
Define this Service into Project's Manifest File:
Add below tag in Manifest file:
<service android:enabled="true" android:name="com.my.packagename.MyService" />
Done
I like to make it more dynamic
Class<?> serviceMonitor = MyService.class;
private void startMyService() { context.startService(new Intent(context, serviceMonitor)); }
private void stopMyService() { context.stopService(new Intent(context, serviceMonitor)); }
do not forget the Manifest
<service android:enabled="true" android:name=".MyService.class" />
Intent serviceIntent = new Intent(this,YourActivity.class);
startService(serviceIntent);
add service in manifist
<service android:enabled="true" android:name="YourActivity.class" />
for running service on oreo and greater devices use for ground service and show notification to user
or use geofencing service for location update in background
reference
http://stackoverflow.com/questions/tagged/google-play-services

Categories

Resources