I want to start count time in my service, when an special event occurred. And i want to do this in worker thread.
even use CountDownTimer() can do this for me.
Problem is here that when i use this method in OnHandleIntent() of IntentService class, i receive an error:
java.lang.IllegalStateException: Handler (android.os.CountDownTimer$1) {235e78c} sending message to a Handler on a dead thread.
Is this the best way to count time and do special work when time arrive to destination? if not how i can? if it is, how solve? Thanks.
My service code is:
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.Environment;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class TimeService extends IntentService {
public TimeService(){
super("");
}
#Override
protected void onHandleIntent(Intent intent) {
new CountDownTimer(20000,1000){
#Override
public void onTick(long millisUntilFinished) {
System.out.println("Time remaining: "+millisUntilFinished/1000);
}
#Override
public void onFinish() {
System.out.println("done");
}
}.start();
}
}
I can not recommend to you to use IntentService. You should use
regular service.
When intent service started, it create a new worker thread and when their task is finished then it terminated. But in your case your are using Countdowntimer, that is running after termination of worker thread, so it throw exception.
One solution you can try:
protected void onHandleIntent(Intent intent) {
Looper.prepare();
new CountDownTimer(20000,1000){
#Override
public void onTick(long millisUntilFinished) {
System.out.println("Time remaining: "+millisUntilFinished/1000);
}
#Override
public void onFinish() {
System.out.println("done");
Looper.myLooper().quit();
}
}.start();
Looper.loop() ;
}
Trying using your countdown timer in Service class as
CountDownTimer countDownTimerVariable;
In #Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
// based on your condition
if(condition)
{
performCountDown();
}
}
public void performCountDown()
{
countDownTimerVariable = new CountDownTimer(remainingMillisForCountDown, 1000) {
#Override
public void onFinish() {
//Action for when the timer has finished.
Log.i("timer finish", "finished");
}
#Override
public void onTick(long millisUntilFinished) {
//Action for every tick of the countdown.
// timeCalculate((millisUntilFinished / 1000));
Log.i("timer finish", "finished" + (millisUntilFinished / 1000) + " Countdown");
}
};
countDownTimerVariable.start();
}
and in destroy of service
#Override
public void onDestroy() {
// TODO Auto-generated method stub
this.unregisterReceiver(notifyServiceReceiver);
super.onDestroy();
if(countDownTimerVariable != null)
countDownTimerVariable.cancel();
}
Related
I have created a Service in my android application which starts running on BOOT_COMPLETE. I want to run my Service non-stop (run always), and for that I have used while(true) inside onStartCommand() method. So is this fine to use while(true) or there is any other better way to run a service always in background?
This is code of my Service:
package com.example.abc.project1;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import org.json.*;
import java.io.*;
import java.net.*;
import java.util.*;
public class HelloService extends Service {
private static final String TAG = "HelloService";
private boolean isRunning = false;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
#Override
public void run() {
while(true) {
/*non-stop work to be done in background always*/
}
}
}).start();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
isRunning = false;
}
}
I have not tried this myself but if you change receiver to service it should work.
i was wondering if the IntentService has thread blocking limit like calling Thread.sleep(); and if so what's the maximum time limit for it?
so i wrote the following code snippet:
package net.yassin.aaaservice;
import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
import android.os.SystemClock;
import android.widget.Toast;
public class MyService extends IntentService {
private Thread t;
private static int i = 0;
private static final int SLEEP_DURATION = 2000;
private Handler handler;
public MyService() {
super("MyService");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
this.handler = new Handler();
}
#Override
protected void onHandleIntent(Intent arg0) {
this.t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
MyService.this.handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyService.this,
"This is toast #" + (++i),
Toast.LENGTH_SHORT).show();
}
});
try {
Thread.sleep(SLEEP_DURATION);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
this.t.start();
}
}
and i found that whenever i change the time SLEEP_DURATION constant to over than 2000 Milis the service will stop showing Toasts if i removed the app form the recent menu?
am i right or there is another time limit or behavior ?
thnx :)
I have an android application and I want to show a notification or toast every 10 seconds for example from Service when application is closed or finished
I have provided below a sample activity, a service class and a Timer class. use similar implementation in your application.
Activity Class
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
public class Sample extends Activity {
Button button1,button2;
private Handler mHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Call the start and stop method when needed.
}
public void Start(View v)
{
startService(new Intent(MainActivity.this , Sample_service.class));
}
public void Stop(View v)
{
stopService(new Intent(MainActivity.this , Sample_service.class));
}
}
Service Class
package com.example.connect;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class Sample_service extends Service{
Timer timer = new Timer();
TimerTask updateProfile = new CustomTimerTask(Sample_service.this);
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
timer.scheduleAtFixedRate(updateProfile, 0, 10000);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show();
timer.cancel();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Timer class
package com.example.connect;
import java.util.TimerTask;
import android.content.Context;
import android.os.Handler;
import android.widget.Toast;
public class CustomTimerTask extends TimerTask {
private Context context;
private Handler mHandler = new Handler();
public CustomTimerTask(Context con) {
this.context = con;
}
#Override
public void run() {
new Thread(new Runnable() {
public void run() {
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(context, "DISPLAY YOUR MESSAGE", Toast.LENGTH_SHORT).show();
}
});
}
}).start();
}
}
I have given here three files,MainActivity,Manifest and MyService file implement it in your application and it will display toast service at every 10 seconds.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//load the layout file
startService(new Intent(this,MyService.class));//use to start the services
}
}
MyService.java
public class MyService extends Service {
public static final long INTERVAL=10000;//variable to execute services every 10 second
private Handler mHandler=new Handler(); // run on another Thread to avoid crash
private Timer mTimer=null; // timer handling
#Nullable
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("unsupported Operation");
}
#Override
public void onCreate() {
// cancel if service is already existed
if(mTimer!=null)
mTimer.cancel();
else
mTimer=new Timer(); // recreate new timer
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),0,INTERVAL);// schedule task
}
#Override
public void onDestroy() {
Toast.makeText(this, "In Destroy", Toast.LENGTH_SHORT).show();//display toast when method called
mTimer.cancel();//cancel the timer
}
//inner class of TimeDisplayTimerTask
private class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast at every 10 second
Toast.makeText(getApplicationContext(), "Notify", Toast.LENGTH_SHORT).show();
}
});
}
}
}
AndroidManifest.xml
<service android:name=".MyService"
android:enabled="true"/>
Technically, When task is executed which you wrote in onCreate() method, It automatically close. For this you can use timer/scheduler.
Example :
Timer timer;
TimerTask timerTask;
timer.schedule(timerTask, 5000, 10000);
timerTask = new TimerTask() {
public void run() {
//use a handler to run a toast that shows the current timestamp
handler.post(new Runnable() {
public void run() {
Toast toast = Toast.makeText(getApplicationContext(), strDate, duration);
toast.show();
}
});
}
};
Don't forget to add your service in the manifest file inside the application Tag :
<service android:name=".ServiceGPS"
android:permission="[Add permission here if exists]"
android:label="[service name]" android:exported="true"
android:enabled="true">
</service>
In this android service I wanna display a toast of value of second at current time. but this again and again show the same value. timer is scheduled to update at interval of 1 second but the value don't refresh and toast shows the previous value again. I don't what the issue.
package net.learn2develop.Services;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.widget.Toast;
public class MyService extends Service{
Handler handler = new Handler();
Calendar c = Calendar.getInstance();
Timer t = new Timer();
int second = c.get(Calendar.SECOND);
int temp = 6;
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public int onStartCommand(Intent intent, int flags, int startId){
Toast.makeText(this,"service started",Toast.LENGTH_SHORT).show();
TimerTask task = new TimerTask() {
#Override
public void run() {
second = timeSecond();
handler.post(new Runnable() {
#Override
public void run() {
// Toast.makeText(getBaseContext(),String.valueOf(second), Toast.LENGTH_SHORT).show();
}
});
}
};
t.scheduleAtFixedRate(task, 0, 4* 1000);
return START_STICKY;
}
public void onDestroy(){
super.onDestroy();
t.cancel();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show();
}
public int timeSecond() {
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(),String.valueOf(c.get(Calendar.SECOND)), Toast.LENGTH_SHORT).show();
}
});
return c.get(Calendar.SECOND);
}
}
This statement:
Calendar c = Calendar.getInstance();
returns a calendar whose time fields have been initialized with the current date and time. Those values do not then change as time passes. So when you use:
String.valueOf(c.get(Calendar.SECOND))
you are getting the same values every time. You need a new instance of calendar in each iteration of your timer.
I want to know if it is possible to call an activity through background service in android like :
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
public class background extends Service{
private int timer1;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
SharedPreferences preferences = getSharedPreferences("SaveTime", MODE_PRIVATE);
timer1 = preferences.getInt("time", 0);
startservice();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
private void startservice() {
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
public void run() {
mediaPlayerPlay.sendEmptyMessage(0);
}
}, timer1*60*1000);
}
private Handler mediaPlayerPlay = new Handler(){
#Override
public void handleMessage(Message msg) {
try
{
getApplication();
MediaPlayer mp = new MediaPlayer();
mp = MediaPlayer.create(background.this, R.raw.alarm);
mp.start();
}
catch(Exception e)
{
e.printStackTrace();
}
super.handleMessage(msg);
}
};
/*
* (non-Javadoc)
*
* #see android.app.Service#onDestroy()
*/
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
i want to call my activity......
You can call an Activity while onStart() of your service.....
Snippet might be as follows:
#Override
public void onStart(Intent intent, int startId) {
...
Log.i("Service", "onStart() is called");
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(<Set your package name and class name here>);
startActivity(callIntent);
...
}
I believe launching user-interactive Activity from a non-interactive Service goes against the design of Android, in that it would pull out control from under the user.
Notifications are the mechanism intended to get user's attention from a background app, and give them an opportunity to launch the interactive Activity.