I develop android app use GCM, i want to send heartbeat for every 5 minutes at once, i create it when service is run,these are my codes,
public class sendHeartbeat extends Service{
private Handler customHandler = new Handler();
private static final String TAG = "MyService";
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
Log.d(TAG, "onCreate");
}
#Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, "onStart");
customHandler.postDelayed(updateTimerThread, 0);
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
}
private Runnable updateTimerThread = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
new syncGetHeartbeat().execute();
Log.d("send hearbeat","send hearrrrrrrbeat");
customHandler.postDelayed(this, 260000);
}
};
class syncGetHeartbeat extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... unsued) {
try {
String varId="naengoland";
String url = "http://mydomain.com/gcmserver/getHeartbeat.php?id="+varId;
getRequestJSON(url);
return null;
} catch (Exception e) {
Log.e(e.getClass().getName(), "service get hertbeat "+ e.toString());
return null;
}
}
#Override
protected void onProgressUpdate(Void... unsued) {
}
#Override
protected void onPostExecute(String sResponse) {
}
}
public String getRequestJSON(String Url){
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(Url);
try{
client.execute(request);
}catch(Exception ex){
}
return null;
}
}
I successfully send the heartbeat for every 5 minutes, but the problem is my app running slowly and consume battery a lot, is there any way to send heartbeat beside doing my way?
i mean,the better method than my method.
Please help.
Using TimerTask provides better performance than using Thread (ref).. However TimerTask isn't good in handling multiple threads at the same time which isn't a concern in your case because you are doing one task repeatedly.
here is the code for Timer:
first initialize a Timer:
private Timer timer;
in onCreate:
timer = new Timer();
then within onStart:
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
new syncGetHeartbeat().execute();
Log.d("send hearbeat","send hearrrrrrrbeat");
}
}, 0, 300000); //means start at 0 second and each 5 mins (300000 ms) run the task
I'm not sure if there is another solution that has better performance however this is absolutely better than running thread in a fixed rate.
Related
Service stop working when turn on /of Wi-Fi many time, when I start service do counter 1,2,3 etc or any thing then turn on /of Wi-Fi many time the service stops working ,I have BroadcastReceiver class doing start service, no exceptions , error appear , only I sent one message to phone to start service..
This is the code inside BroadcastReceiver:
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Intent recorderIntent = new Intent(context, Start2.class);
context.startService(recorderIntent);
}
This My Start2 Service:
public class Start2 extends Service {
private static final String TAG = Start2.class.getSimpleName();
int mStartMode;
#Override
public void onDestroy() {
Log.d(TAG, "Stop Service onDestroy");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
final Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
int i = 0 ;
#Override
public void run() {
try{
//do your code here
Log.d(TAG, "Start Service Repeat Time.. " + i);
i++;
}
catch (Exception e) {
// TODO: handle exception
}
finally{
//also call the same runnable to call it at regular interval
handler.postDelayed( this, 5000 );
}
}
};
handler.postDelayed(runnable, 1000 );
return null;
}
};
task.execute();
return mStartMode;
}
}
I am making AsynkTask within Service like this
public class MyService extends Service {
private final IBinder mBinder = new LocalBinder();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v("log_tag", "Service started");
ReceiveAsyncTask receiveATask = new ReceiveAsyncTask();
receiveATask.execute();
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
Log.v("log_tag", "onBind");
return mBinder;
}
public class LocalBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
class ReceiveAsyncTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
taskDummy();
return null;
}
#Override
protected void onPreExecute() {
Log.v("log_tag", "onPreExecute");
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
Log.v("log_tag", "onPostExecute");
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
Log.v("log_tag", "onPostExecute");
super.onCancelled();
}
}
private void taskDummy() {
while (true) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.v("log_tag", "taskDummy");
}
}
/** method for clients */
public int getRandomNumber() {
Log.v("log_tag", "inner Method called");
return 100;
}
}
when I am running the application it starting to print "taskDummy" every two second as expected, when I close application by prssing Back buttin still log printing continue as expected, but when I removed application from recent apps stack it stopped printing this should not happen I want my asynch task continue in this situation. even I can see my service is running from setting. please advise me.
You need to explicitly call of asyncTaskObject.cancel(true); in onDestroy of your Activity(Or your event whenever you want.)
And then rewrite your while loop logic , something like that:
// Create this variable is Your Asyantask class.
private boolean isRunning = true;
#Override
protected void onCancelled() {
isRunning = false;
}
#Override
protected String doInBackground(Void... params) {
while (isRunning ) {
// Your processing
}
return null;
}
It's a known bug: swiping the service out from recent apps destroys it.
Try following solution.
Hi everybody and Merry Christmas.
Please see this snippet of code.
As you can see there is an Handler that receives messages form a Service.
When the Activty is destroyed, I take care of destroying the Service, nevertheless it seems like the Service is still sending back messages to the Handler (which I don't think it is the case).
For some reason the Handler seems to stay alive and post:
Log.e("","MESSAGGIO RICEVUTO");
like it is continuing to receive messages.
Thanks for your help!!!
private String url;
private String url2;
private WebView browser;
private HttpClient client;
private List<Forecast> forecasts=new ArrayList<Forecast>();
public String responseBody;
public ArrayList<Stock> lt;
public LocalService mService;
boolean mBound = false;
public MyAdapter myAdap;
public Messenger messenger;
public Grab g;
public Handler handler;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
url2=getString(R.string.url2);
Log.e("", "arrivo a prima di forecast");
g = new Grab(url2);
String s = g.vai();
Log.e("", s);
Log.e("", "passo oltre l'invocazione al grab");
lt = new MyParser(s).parseResp();
ListView lv = (ListView)findViewById(android.R.id.list);
myAdap= new MyAdapter(lt, this);
lv.setAdapter(myAdap);
lv.setOnItemClickListener(new myListener());
handler=new Handler() {
#Override
public void handleMessage(Message msg) {
Log.e("","MESSAGGIO RICEVUTO");
lt = mService.ritira();
myAdap.notifyDataSetChanged();
g.fermaGrab();
}
};
messenger = new Messenger(handler);
}
This is the Service:
public class LocalService extends Service {
public Messenger messenger;
public int i;
public ArrayList<Stock> al;
public DefaultHttpClient client;
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
public Task t;
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
Log.e("", "sono nel service");
messenger = (Messenger) intent.getExtras().get("messenger");
return mBinder;
}
class Task extends AsyncTask<Void, String, Void> {
#Override
protected Void doInBackground(Void... unused) {
Log.e("Sono nel AsyncTask del Service", Integer.toBinaryString(i));
/////////INIZIA IL CASINO
client=new DefaultHttpClient();
for(int in=0;;in++)
{
for(int i=0;i<al.size();i++)
{
String srt="";
String url =getString(R.string.dettaglio1).concat("'"+al.get(i).simbolo+"'").concat(getString(R.string. dettaglio2));
HttpGet getMethod=new HttpGet(url);
try {
ResponseHandler<String> responseHandler=new BasicResponseHandler();
srt=client.execute(getMethod, responseHandler);
//Log.e("", "passo per GrabXML");
int inizio = srt.indexOf("<company data=\"");
int fine = srt.indexOf("\"/>",inizio+15);
String s =srt.substring(inizio+15,fine).substring(0, 10);
al.get(i).setNome(s);
Log.e("",al.get(i).nome);
//Log.e("",Integer.toString((al.get(i).nome.length())));
inizio = srt.indexOf("<last data=\"");
fine = srt.indexOf("\"/>",inizio+12);
al.get(i).setPrezzo(srt.substring(inizio+12,fine));
//Log.e("",Float.toString(al.get(i).prezzo));
inizio = srt.indexOf("<perc_change data=\"");
fine = srt.indexOf("\"/>",inizio+19);
al.get(i).setCambiamento(srt.substring(inizio+19,fine));
//Log.e("",Float.toString(al.get(i).cambiamento));
}
catch (Throwable t) {
android.util.Log.e("grabXML", "Exception fetching data", t);
}
}
/////////INIZIA IL CASINO
Collections.sort(al, new Comparator<Stock>(){
public int compare(Stock s1, Stock s2) {
return s1.nome.compareToIgnoreCase(s2.nome);
}
});
Message msg=Message.obtain();
try {
messenger.send(msg);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SystemClock.sleep(6000);
}
/////////FINISCE IL CASINO
}
#Override
protected void onProgressUpdate(String... unused) {
}
#Override
protected void onPostExecute(Void unused) {
}
}
public void stop() {
Log.e("", "passo per lo stop del Service");
t.cancel(true);
client.getConnectionManager().shutdown();
return;
}
}
I shut down the Service on the main Activity in the onDestroy():
protected void onDestroy() {
Log.e("ondestroy","passo per ondestroy");
//handler.removeMessages();
mService.stop();
g.fermaGrab();
handler.removeMessages(333);
//g=null;
super.onDestroy();
}
You're continuing receiving a message from your service because of this infinite loop
class Task extends AsyncTask<Void, String, Void> {
#Override
protected Void doInBackground(Void... unused) {
for (int in = 0;; in++) {
// .. Other definition
Message msg = Message.obtain();
try {
messenger.send(msg);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SystemClock.sleep(6000);
}
}
}
A conditionless for-loop is doing an infinite process, so your service's thread is still sending you a message right?
Just put !isCancelled() in your loop, and you can now stop your loop and Asynctask
for (int in = 0; !isCancelled() ; in++) {
// ...
}
Please see this. It is not answer to your question. It will help you to get answer,
How to stop the handler?
First I will explain the current situation.
I've 2 different threads in 2 services(read from usb port service and make web requests service). I'm starting them in onCreate of my activity like:
serialServiceIntent = new Intent(NDKSerialActivity.this, SerialService.class);
startService(serialServiceIntent);
webServiceIntent = new Intent(NDKSerialActivity.this, RecordWebService.class);
startService(webServiceIntent);
There is nothing wrong with serial service but in RecordWebService when I make a request my gui stops until response comes.
The code is like that:
public class RecordWebService extends Service
{
public static final String SERVER_ADDRESS = "http://192.168.1.100:8080/MobilHM/rest";
private static final String TAG = RecordWebService.class.getSimpleName();
private RecordWebThread recordWebThread;
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
recordWebThread = new RecordWebThread(true);
recordWebThread.start();
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.i(TAG, "RecordWebService Destroyed");
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
and
public class RecordWebThread extends Thread
{
private static final String TAG = RecordWebThread.class.getSimpleName();
public boolean always;
public RecordWebThread(boolean always)
{
this.always = always;
}
#Override
public void run()
{
PatientRecord patientRecord = new PatientRecord();
while (always)
{
RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
try
{
restClient.execute(RequestMethod.GET);
}
catch (Exception e1)
{
Log.e(TAG, "", e1);
}
Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
Log.i(TAG, "Server Response:->" + restClient.getResponse());
try
{
sleep(4 * 1000);
}
catch (InterruptedException e)
{
Log.e(TAG, "Web service interrupted", e);
}
}
}
}
Also I've tried to remove sleep part and make the thread to run with timer and timer task like:
public void sendRecord()
{
scanTask = new TimerTask()
{
public void run()
{
handler.post(new Runnable()
{
public void run()
{
RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
try
{
restClient.execute(RequestMethod.GET);
}
catch (Exception e1)
{
Log.e(TAG, "", e1);
}
Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
Log.i(TAG, "Server Response:->" + restClient.getResponse());
}
});
}
};
t.schedule(scanTask, 1000, 4000);
}
but no luck, my gui hangs when it comes to restClient.execute .
You can find RestClient.java # http://www.giantflyingsaucer.com/blog/?p=1462
How can I make my requests not block my gui thread?
Edit:
public void sendRecord()
{
scanTask = new TimerTask()
{
public void run()
{
RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
try
{
restClient.execute(RequestMethod.GET);
}
catch (Exception e1)
{
Log.e(TAG, "", e1);
}
Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
Log.i(TAG, "Server Response:->" + restClient.getResponse());
}
};
t.schedule(scanTask, 1000, 4000);
}
Without handler, I call this in onCreate of my activity but still ui hanging.
Or you can use an IntentService which will handle the thread issues for you.
This is an example class:
public class MyService extends IntentService {
public MyService() {
super("MyService");
}
public MyService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent arg0) {
//Do what you want
}
}
Then you just call:
Intent intent = new Intent(getApplicationContext(),MyService.class);
startService(intent);
Edit:
To repeat the same thing every 4 seconds you should do something like this:
PendingIntent serviceIntent= PendingIntent.getService(context,
0, new Intent(context, MyService.class), 0);
long firstTime = SystemClock.elapsedRealtime();
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
long intervalInSec = 4;
am.setRepeating(AlarmManager.ELAPSED_REALTIME, firstTime, intervalInSec*1000, serviceIntent)
;
In your code (2d version) happens next: You create thread, and it asks UI thread to do some net interaction. Just exclude handler.post(...) while executing request. Later you can use this for simple runnable for updating your UI with results of request.
How to make Async task execute repeatedly after some time interval just like Timer...Actually I am developing an application that will download automatically all the latest unread greeting from the server and for that purpose I have to check for updates from server after some fixed time intervals....I know that can be easily done through timer but I want to use async task which I think is more efficient for android applications.
public void callAsynchronousTask() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
PerformBackgroundTask performBackgroundTask = new PerformBackgroundTask();
// PerformBackgroundTask this class is the class that extends AsynchTask
performBackgroundTask.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 50000); //execute in every 50000 ms
}
//Every 10000 ms
private void doSomethingRepeatedly() {
Timer timer = new Timer();
timer.scheduleAtFixedRate( new TimerTask() {
public void run() {
try{
new SendToServer().execute();
}
catch (Exception e) {
// TODO: handle exception
}
}
}, 0, 10000);
}
You can just a handler:
private int m_interval = 5000; // 5 seconds by default, can be changed later
private Handle m_handler;
#Override
protected void onCreate(Bundle bundle)
{
...
m_handler = new Handler();
}
Runnable m_statusChecker = new Runnable()
{
#Override
public void run() {
updateStatus(); //this function can change value of m_interval.
m_handler.postDelayed(m_statusChecker, m_interval);
}
}
void startRepeatingTask()
{
m_statusChecker.run();
}
void stopRepeatingTask()
{
m_handler.removeCallback(m_statusChecker);
}
But I would recommend you to check this framework: http://code.google.com/intl/de-DE/android/c2dm/ Is a different approach: the server will notify the phone when something is ready (thus, saving some bandwidth and performance:))
wouldn't it be more efficient to create a service and schedule it via Alarm Manager?
The accepted answer is problematic.
Using TimerTask() for activating async task via handler is a bad idea. on orientation change you must remember to cancel also the timer and the handler calls. if not it will call the async task again and again on each rotation.
It will cause the application to blow up the server (if this is rest http get request) instead of X time - eventually the calls will be instance many calls on each second. (because there will be many timers according to the number of screen rotations). It might crush the application if the activity and the task running in background thread are heavy.
if you use the timer then make it a class memebr and cancel it onStop():
TimerTask mDoAsynchronousTask;
#Override
public void onStop(){
super.onStop();
mDoAsynchronousTask.cancel();
mHandler.removeCallbacks(null);
...
}
public void callAsynchronousTask(final boolean stopTimer) {
Timer timer = new Timer();
mDoAsynchronousTask = new TimerTask() {
#Override
public void run() {
mHandler.post(new Runnable() {
...
Instead try to avoid async task, and if you must then use scheduler service to run the async task. or the application class such as in this nice idea:
https://fattybeagle.com/2011/02/15/android-asynctasks-during-a-screen-rotation-part-ii/
Or use simple handler (without the timer, just use postDelayed) and also good practive is to call cancel the async task onStop(). this code works fine using postDelayed:
public class MainActivity extends AppCompatActivity {
MyAsync myAsync = new MyAsync();
private final Handler mSendSSLMessageHandler = new Handler();
private final Runnable mSendSSLRunnable = new Runnable(){
..
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
mSendSSLMessageHandler.post(mSendSSLRunnable);
}else
..
#Override
public void onStop(){
super.onStop();
if ( progressDialog!=null && progressDialog.isShowing() ){
progressDialog.dismiss();
}
mSendSSLMessageHandler.removeCallbacks(mSendSSLRunnable);
myAsync.cancel(false);
}
private final Runnable mSendSSLRunnable = new Runnable(){
#Override
public void run(){
try {
myAsync = new MyAsync();
myAsync.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
mSendSSLMessageHandler.postDelayed(mSendSSLRunnable, 5000);
}
};
class MyAsync extends AsyncTask<Void, Void, String> {
boolean running = true;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show
(MainActivity.this, "downloading", "please wait");
}
#Override
protected String doInBackground(Void... voids) {
if (!running) {
return null;
}
String result = null;
try{
URL url = new URL("http://192...");
HttpURLConnection urlConnection = (HttpURLConnection)
url.openConnection();
InputStream in = new BufferedInputStream (urlConnection.getInputStream());
result = inputStreamToString(in);
}catch(Exception e){
e.printStackTrace();
}
return result;
}
#Override
protected void onCancelled() {
boolean running = false;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
progressDialog.dismiss();
try {
..
} catch (JSONException e) {
textView.append("json is invalid");
e.printStackTrace();
}
}
}