I am writing a Location Service, with a update Interval to send the Location updates to the server.
But I trying to update this interval variable in the service via user input(AlertDialog). It works perfectly fine when hard coded.
I am using this code to get the interval variable from the AlertDialog class, in the onCreate() of the service.
public void onCreate() {
super.onCreate();
final boolean tr=true;
new Thread(new Runnable() {
public void run() {
while (tr) {
//check your static variable here
updateInterval=ShowCurInterval.loadCurInterval(getApplicationContext());//ShowCur Interval is the Alert Dialog calss
Log.d(" INTERVAL ","Interval "+ updateInterval);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}}
).start();
startLocationListener(updateInterval);
}
And I can also see the new updateInterval value in Log ( which is added from the Alert Dialog). But requestLocationUpdates() still uses the pre defined updateInterval value.
Here is the startLocationListener() method:
public void startLocationListener(int updateInterval) {
LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locManager.removeUpdates(locListener);
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, updateInterval, updateDistance, locListener);
Log.d(getClass().getSimpleName(), "Loclistener started, Updatetime: " + updateInterval);
Toast.makeText(getApplicationContext(), "UPDATE INTERVAL"+updateInterval,Toast.LENGTH_SHORT );
preInterval = updateInterval;
}
Does anyone have any suggestions how can I update this variable?
#binW
Edited part with exception:
Handler mhandler = new Handler ();
mhandler.postDelayed( new Runnable(){
public void run(){
Looper.prepare();
updateInterval=SingletonManager.getInstance().loadCurInterval(getApplicationContext());
SingletonManager.getInstance().saveCurInterval(getApplicationContext(), updateInterval);
startLocationListener(updateInterval);
Log.d(" INTERVAL ","Interval "+ updateInterval);
//startChecking();
}
}, 2000);
Exception:
04-17 03:18:55.250: E/AndroidRuntime(2146): java.lang.RuntimeException: Only one Looper may be created per thread
Thank You in advance.
you are calling startLocationListener() in onCreate() and not in the thread that you created for getting the new value of updateInterval. But the call to startLocationListener(updateInterval); gets executed before the new thread executes and hence you get the old value of updateInterval. I believe you should change your code to following:
public Handler handler;
public void onCreate() {
super.onCreate();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
startLocationListener(updateInterval);
}
};
final boolean tr=true;
new Thread(new Runnable() {
public void run() {
while (tr) {
//check your static variable here
updateInterval=ShowCurInterval.loadCurInterval(getApplicationContext());//ShowCur Interval is the Alert Dialog calss
handler.sendEmptyMessage(1);
Log.d(" INTERVAL ","Interval "+ updateInterval);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}}
).start();
}
Related
I'm currently trying to do an app that keeps track of the phone through the GPS by using a service. in order to get the GPS to update the coordinates, I need to use a handler within the service. Right now the proble I have is that when the I do the Handler.post, it gets stuck in an loop, and after that, it completely ignores the rest of the service code.
When I was debugging, I found out that the handler was alternating messages between methods but nothing useful came out of it, it was just a loop between the same methods over and over again.
Here's my Service code that includes the handler:
public int onStartCommand(Intent intent, int flags, int startId)
{
ctx = ServicioDeFondo.this;
mHandler = new Handler();
reportarGPS = new Thread(new Runnable() { public void run()
{
try
{
while(true)
{
mHandler.post(new Runnable() {
#Override
public void run() {
gps = new GPSTrack(ctx);
latitude = String.valueOf(gps.getLatitude());
longitude = String.valueOf(gps.getLongitude());
}
});
Thread.sleep(10000);
try {
new APISendClass().execute();
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
catch (Exception e)
{
//TODO Auto-generated catch block
e.printStackTrace();
}
} });
reportarGPS.start();
return START_STICKY;
}
I"ve been stuck here all day, any help would be greatly appreciated!
With your brief description of the problem, it's hard to understand what the expected behavior is. You don't explain what GPSTrack and APISendClass do and what type of objects that are. You state "it gets stuck in a loop". It's not clear what "it" is. With the while (true) statement, the thread will loop until cancelled.
Note that Service methods, such as onStartCommand() run on the main thread. That means that your Handler() constructor associates the handler with the main thread. The runnables you post to that handler run on the main thread. Is that what you wanted?
Also note that stopping the service by stopSelf() or Context.stopService() does not kill the thread. You need to have code to cancel the thread when it is no longer needed. This is often done in onDestroy().
I took the code you posted, replaced the calls to unknown objects with Log statements and ran it. The logcat output alternated between "Get lat/long" and "APISendClass()".
Handler mHandler;
Context ctx;
Thread reportGPS;
public int onStartCommand(Intent intent, int flags, int startId){
Log.i("TEST", "onStartCommand()");
ctx = this;
// Service methods run on main thread.
// Handler constructor with no args associates Handler
// with current thread, which here is the main thread.
mHandler = new Handler();
reportGPS = new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
mHandler.post(new Runnable() {
#Override
public void run() {
// This runnable is posted to the main thread.
// Is that what you intended?
//gps = new GPSTrack(ctx);
//latitude = String.valueOf(gps.getLatitude());
//longitude = String.valueOf(gps.getLongitude());
Log.i("TEST", "Get lat/long");
}
});
Thread.sleep(2000);
try {
//new APISendClass().execute();
Log.i("TEST", "APISendClass().execute()");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
reportGPS.start();
return START_STICKY;
}
Hi currently i have the following code which utilizes Asycn Task and Timer.
My async task is basically trying to send a HTTP GET method from a URL where the response from the server could varies depending on connection and load.
What i would like to do is to have a timed async task. Where, it will schedule an AsyncTask every X second BUT if there is currently an Async Task in progress i would have to kill it first. Then start a new one.
Here is the code that i have at the moment:
private static boolean running = false;
Timer myTimer;
protected void onCreate(Bundle savedInstanceState) {
/* REST OF CODE OMITTED */
MyTimerTask myTask = new MyTimerTask();
myTimer = new Timer();
myTimer.schedule(myTask, 0, 10000);
}
/* REST OF CODE OMITTED */
private class MyTimerTask extends TimerTask {
public void run() {
if(!running){
Log.i("TAG", "NEW TIMER STARTED.");
RetrieveChatMessage task = new RetrieveChatMessage();
task.execute();
running = true;
}else{
running = false;
}
}
}
private class RetrieveChatMessage extends AsyncTask<String, Void, ArrayList<Chat>> {
#Override
protected ArrayList<Chat> doInBackground(String... params) {
// TODO Auto-generated method stub
ArrayList<Chat> cList = null;
String jResult = null;
Log.i("TAG", "RETRIEVING CHAT MESSAGE");
try {
jResult = ((new HttpRetriever())).getChatList(mAccount.email, mAccount.passwd);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(jResult != null){
Log.i("TAG", "JSON DATA: " + jResult);
cList = (new ChatHandlers()).getChatList(jResult);
}else{
cList = null;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("TAG", "JSON Exception " + e.toString());
}
return cList;
}
#Override
protected void onPostExecute(final ArrayList<Chat> result) {
Log.i("TAG", "ON POST EXECUTE");
if(result != null){
// Do something here
}
}
}
To be honest the code above works with slight issues:
1. It seems to execute the Async randomly, instead of every 10 seconds.
2. When i go to another activity, somewhat it prevents other Async task from doing its job (Which is also trying to retrieve JSON response from server).
I am not too worried about the later problem (and that is not the question i am asking). I just would like to know how to have a proper timed Async Task. Can anyone point me to a direction.
Thank you.
EDIT #1:
after reading #thepoosh comment's i tried the following (i put it in onCreate):
scheduleTaskExecutor= Executors.newScheduledThreadPool(5);
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
// Parsing RSS feed:
// myFeedParser.doSomething();
Log.w("THUMBQOO", "NEW TASK STARTED");
retrieveChat();
}
}, 0, 15, TimeUnit.SECONDS);
Result: i have a consistent execution of Task. However, it seems that retrieveChat(); is never be called after the first execution.
Actually AsyncTask is not used for long operations .Check Here
You should use a Thread that uses a interface to notify UI or you can simply use a Handler which is the most Preffered way in android. Simply you can do a task repeatedly for every 10 seconds by
handler.postDelayed(new Runnable() {
#Override
public void run() {
// do work
handler.postDelayed(10000);
}
}, 10000);
Declare a Handler object to maintain future task executor...
private Handler mTimerHandler = new Handler();
Write a thread which will execute your future task...
private Runnable mTimerExecutor = new Runnable() {
#Override
public void run() {
//write your code what you want to do after the specified time elapsed
if(!running){
RetrieveChatMessage task = new RetrieveChatMessage();
task.execute();
running = true;
}else{
running = false;
}
}
};
Call your future tast executor with time using hanlder...
mTimerHandler.postDelayed(mTimerExecutor, 10000);
You can cancle your future task executor any time by this...
mTimerHandler.removeCallbacks(mTimerExecutor);
I am not sure if this is a very good way of accomplishing this (my answer here below) :
Use a Handler, create a HandlerThread and keep posting messages to this handler.
For the handlers "handleMessage" method, you can do your task and again send a message back to the MessageQueue.
HandlerThread thread = new HandlerThread(<name>);
thread.start();
Looper looper = thread.getLooper();
CustomHandler handler = new CustomHandler(looper);
// The CustomHandler class
class CustomHandler extends Handler {
public CustomHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
//Do your operation here
handler.sendEmptyMessageDelayed(msg, <delayTime>);
}
}
I have an application which starts a new service. In this service I currently have a handler that does some work every minute and then sends the results to the main activity through a BroadcastReceiver. I want the following thing: Every minute create a new thread inside the service, make it do the work and send a message to the handler that it is finnished and then the handler will send to the main activity through a BroadcastReceiver. How can i combine the Thread and the Handler? Here is what I have so far -only part of code of interest-
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
try {
getAppResources(); //this is the work i want to place in a new thread
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
intent.putExtra(key,value);
sendBroadcast(intent);
handler.postDelayed(this, 60*1000);
}
};
Here is what i understand i need to do
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
/* try {
getAppResources();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
Thread t = new Thread() {
#Override
public void run(){
try {
getAppResources();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
};
handler.postDelayed(this, 60*1000);
}
};
And where do i place the handleMessage ? If i place it inside the Runnable it says it is never used locally. I just place it right before the Runnable ?
public void handleMessage(Message msg){
if(msg.what == 0){
intent.putExtra(key,value);
sendBroadcast(intent);
}
}
Is this how I should do it ?
EDIT: Handler code that sends to the main activity some data
private final Handler handler = new Handler(){
public void handleMessage(Message msg){
if(msg.what == 0){
Log.d("HANDLE","Am primit mesaj");
//Notify preparations
intent.putExtra("RunningApps", runningApps.size());
intent.putExtra("CPU", highestDrainPackageCPU);
intent.putExtra("GPS",highestDrainPackageGPS);
intent.putExtra("WIFI", highestDrainPackageWIFI);
//Now i have all my data, time to send them to the activity
//First , send the strings to be set in the TextViews
//Each running app has 7 messages to display -> ArrayList<String>
for(int i=0;i<runningApps.size();i++){
intent.putStringArrayListExtra(String.valueOf(i), appInfo.get(i));
}
//Next send values to plot the chart
//CPU energy consumption for highest draining application
double [] currValues_cpu = new double[tableCPU.get(highestDrainPackageCPU).size()];
Log.d("CPUSIZE",String.valueOf(currValues_cpu.length));
for(int j=0;j<tableCPU.get(highestDrainPackageCPU).size();j++){
currValues_cpu[j]=tableCPU.get(highestDrainPackageCPU).get(j);
Log.d("CPUVALUE",String.valueOf(currValues_cpu[j])+"For application"+highestDrainPackageCPU);
}
intent.putExtra("highestDrainPackageCPU", currValues_cpu);
//GPS energy consumption for highest draining application
double [] currValues_gps = new double[tableGPS.get(highestDrainPackageGPS).size()];
for(int j=0;j<tableGPS.get(highestDrainPackageGPS).size();j++){
currValues_gps[j]=tableGPS.get(highestDrainPackageGPS).get(j);
}
intent.putExtra("highestDrainPackageGPS", currValues_gps);
//WIFI energy consumption for highest draining application
double [] currValues_wifi = new double[tableWIFI.get(highestDrainPackageWIFI).size()];
for(int j=0;j<tableWIFI.get(highestDrainPackageWIFI).size();j++){
currValues_wifi[j]=tableWIFI.get(highestDrainPackageWIFI).get(j);
}
intent.putExtra("highestDrainPackageWIFI", currValues_wifi);
sendBroadcast(intent);
}
}
};
Here is the BroadcastReceiver in the Main Activity and the UpdateUI function:
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
public void updateUI(Intent intent){
resourceTab.removeAllViews();
//statisticsTab.removeAllViews();
int apps_no = intent.getIntExtra("RunningApps", 0);
String highestDrainPackageCPU = intent.getStringExtra("CPU");
String highestDrainPackageGPS = intent.getStringExtra("GPS");
String highestDrainPackageWIFI = intent.getStringExtra("WIFI");
//TO-DO: Get information for each app and store it in textview.Then add it to a linearlayout
for(int i=0;i<apps_no;i++){
//Setup delimiter
View delimitator = new View(this);
delimitator.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,1));
delimitator.setBackgroundColor(Color.parseColor("#50FFFFFF"));
//Extract values
ArrayList<String> info = new ArrayList<String>();
info=intent.getStringArrayListExtra(String.valueOf(i));
for(int j=0;j<info.size();j++){
TextView infoApp = new TextView(this);
//////Setup textview//////////
infoApp = new TextView(this);
infoApp.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
infoApp.setTextColor(Color.parseColor("#FFFFFF"));
infoApp.setText(info.get(j));
resourceTab.addView(infoApp);
}
//Add delimiter
resourceTab.addView(delimitator);
}
double [] cpu_values = intent.getDoubleArrayExtra("highestDrainPackageCPU");
double [] gps_values = intent.getDoubleArrayExtra("highestDrainPackageGPS");
double [] wifi_values = intent.getDoubleArrayExtra("highestDrainPackageWIFI");
//Now plot the graph
createGraphOverall(cpu_values, gps_values, wifi_values, highestDrainPackageCPU, highestDrainPackageGPS, highestDrainPackageWIFI);
//Update the table
updateTable(cpu_values, gps_values, wifi_values, highestDrainPackageCPU, highestDrainPackageGPS, highestDrainPackageWIFI);
}
My Activity was successfully updated before I tried to create a new thread to do the heavy work inside the service.
EDIT: Sorry, I think I noticed it earlier, and got side tracked with the handler.
You create Thread t, but you never run it.
t.start();
You define handleMessage() as a method of the handler, like this:
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//TODO: Handle different types of messages
}
};
I have developed a service which includes timer task and runs after every 5 minutes for keeping tracking record of the device, every five minutes it adds a record to the database.
My service is working fine when the phone is not moving i.e it gives records after every 5 minutes as it should be. But i have noticed that when the phone is on move it updates the points after 10 or 20 minutes , i.e whenever the user stops in his way whenever he is on the move.
Do service freezes on the move, if yes! how is whatsapp messenger managing it??
Please help!
i am writing my onstart method. please help
#Override
public void onStart(Intent intent, int startId) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
mLocationClient.connect();
final Handler handler_service = new Handler();
timer_service = new Timer();
TimerTask thread_service = new TimerTask() {
#Override
public void run() {
handler_service.post(new Runnable() {
#Override
public void run() {
try {
some function of tracking
}
});
}
};
timer_service.schedule(thread_service, 1000, service_timing);
//sync thread
final Handler handler_sync = new Handler();
timer_sync = new Timer();
TimerTask thread_sync = new TimerTask() {
#Override
public void run() {
handler_sync.post(new Runnable() {
#Override
public void run() {
try {
//connecting to the central server for updation
Connect();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer_sync.schedule(thread_sync,2000, sync_timing);
}
I need a thread (it does httppost ,and parse the answer xml and refresh listview to set the changes from parsed xml) in 3 sec interval
I have already tried this code
Timer timer = new Timer();
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
try {
httpPostList(url);
saxParseList();
list.invalidateViews();
Thread.sleep(1000);
} catch (Exception ie) {
}
}
}, 1000, 1000 * 30);
I would appreciate you to create a Service with an AsyncTask in it.
Async Tasks are the Android Synonym to normal Java Tasks, Documentation finding here: http://developer.android.com/reference/android/os/AsyncTask.html
Services are Background Processes, seeing this Doc:
http://developer.android.com/reference/android/app/Service.html
Try using handlers:
Handler handler;
#Override
public void onCreate(Bundle savedInstanceState) {
// ...
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
updateUI();
}
};
Thread thread = new Thread() {
#Override
public void run() {
while(true) {
Message msg = new Message();
handler.sendMessage(msg);
try {
sleep(3*1000); // 3 seconds
} catch (InterruptedException e) {
}
}
}
};
thread.start();
}
private synchronized void updateUI() {
// ...
}
Finally I made it using "Async task".