I have a activity that call startService(intent) and this one in his method onStatCommand() create a thread that checks the running app every second.
The problem is that the thread freze the creation of the activity and the screen show only a white screen. If i delete the for(;;) statment in the thread it works. why?
here there is the onStartCommand() code:
#Override
public int onStartCommand(Intent intent,int flags,int startid)
{
super.onStartCommand(intent,flags,startid);
final Thread thread= new Thread(){
#Override
public void run()
{
Context context = getApplicationContext();
for(;;) {
long current = System.currentTimeMillis();
UsageStatsManager usageStatsManager = ((UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE));
for (UsageStats usageStats : usageStatsManager.queryAndAggregateUsageStats( current - 1000*2, current).values()) {
Log.i("Path changed name",usageStats.getPackageName());
if(usageStats.getPackageName()=="com.android.chrome")
{
Log.i("Path name",usageStats.getPackageName());
stopSelf();
break;
}
}
try {
currentThread().sleep(1000);
}catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
};
thread.run();;
return 0;
}
There is problem with Thread code, You should call Start method to start a new Thread not run.
Problem code:
thread.run();
Fixed code:
thread.start();
Related
So I'm trying to update an overlay with a timer however it always crashes. I read something about UI thread but I'm kinda lost on what that even means.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
overlayView.getBackground().setAlpha(50);
windowManager.addView(overlayView, params);
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//crashing here//
overlayView.getBackground().setAlpha(150);
//testing if updating
counter = counter + 1;
notification.setContentText("number" + counter);
startForeground(1, notification.build());
}
}
}).start();
return START_NOT_STICKY;
}
It always returns this error:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the
original thread that created a view hierarchy can touch its views.
Android do not allow updating UI from any thread except UI/Main thread. I see you have created a new Thread so your updating UI stuff is on a worker thread which is not allowed in Android.
A simple solution is to create a handler of main thread and post a runnable to it.
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
// modify UI here
// overlayView.getBackground().setAlpha(150);
}
});
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;
}
I am using a DatagramSocket to receive packets in background (using service). but it does not receive when my phone is locked while when I add a ScheduledTask to start the thread every 1 sec, it works well. Why it doesn't work in first case and how can I fix it whitout starting the Tread every 1 sec?
public class RecThread2 implements Runnable {
public void run() {
while(running){
try {
int MESSAGE_LEN = 60;
byte[] recvBuffer = new byte[MESSAGE_LEN];
DatagramPacket datagram = new DatagramPacket(recvBuffer,
MESSAGE_LEN);
socket1.receive(datagram);
String recvdString = new String(recvBuffer);
Log.i("Recieved", recvdString);
mess = recvdString;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
and I run the thread here:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "receiveTag");
wl.acquire();
Thread sThread2 = new Thread(new runSoc1());
sThread2.start();
return super.onStartCommand(intent, flags, startId);
}
But when I use the following code to run Thread periodically it works even when the phone is locked (and I remove the while(running) from the Thread code):
time = new Timer();
ScheduledTask st = new ScheduledTask();
time.schedule(st, 0, 1000);
and :
public class ScheduledTask extends TimerTask {
public void run() {
Thread sThread2 = new Thread(new RecThread2());
sThread2.start();
}
}
I have a service B that sends a specific number of messages in a fixed interval.
this service is called from another service A.
the code used in service A is
#Override
public void onStart (Intent intent,int startid)
{
Toast.makeText(this, "Service A Running onStart", Toast.LENGTH_LONG).show();
Thread MessagesThread = new Thread(new Runnable()
{
public void run()
{
ApplicationPreferences AppPrefs = new ApplicationPreferences(getApplicationContext());
int NumberOfMessagesToSend = Integer.parseInt(AppPrefs.getNumberOfMessagesToSend());
int NumberOfSentMessages;
for (NumberOfSentMessages = 0 ; NumberOfSentMessages < NumberOfMessagesToSend; NumberOfSentMessages++ )
{startServiceB();
}
}
});
MessagesThread.start();
}
public void startServiceB()
{
final Intent sendingMessages = new Intent(this, ServiceB.class);
startService(sendingMessages);
}
the toasts are to keep track of what is happening
The code in service B is as follow
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
Toast.makeText(getApplicationContext(), "Service B at start ", Toast.LENGTH_LONG).show();
new CountDownTimer(30000,1000)
{
public void onTick (long millisUntilFinished) {}
public void onFinish()
{
showToast();
}
}.start();
}
the showToast() function is as follow
public void showToast()
{
Toast.makeText(getApplicationContext(), "Service B in timer", Toast.LENGTH_LONG).show();
}
As I said I am using the toasts to keep track of what's happening. the problem is when running it, i am getting the first toast (service B at start) 10 times consequently then the second one (service B in timer) 10 times consequently with no time between them.
how do i make each of this toasts appear once every 30 seconds?
Ok, so the final answer could be something like this:
Call only once the B service and in it we will have the handler that will loop at an interval of 30 seconds..
Service B code:
int loop = 5;
int counter = 0;
Handler myHandler;
Runnable run;
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
Toast.makeText(getApplicationContext(), "Service B at start ", Toast.LENGTH_LONG).show();
myHandler = new Handler();
run = new Runnable()
{
public void run()
{
if (counter<loop){
showToast();
counter++;
} else {
myHandler.removeCallbacks(run);
}
}
};
myHandler.postDelayed(run, 30000);
}
I hope this helps someone else too!
If you want to make a toast every 30 seconds than you can do it by using a handler:
Handler myHandler = new Handler();
Runnable run = new Runnable()
{
public void run()
{
showToast();
}
};
myHandler.postDelayed(run, 30000);
If you have problem with this just post here and I will try to help you..
I am developing an Android app and I am doing some heavy work (bringing data from an online web page and parsing it to store in database) in a service. Currently, it is taking about 20+ mins and for this time my UI is stuck. I was thinking of using a thread in service so my UI doesn't get stuck but it is giving error. I am using the following code:
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
Toast.makeText(getBaseContext(), "Running Thread...", Toast.LENGTH_LONG).show();
}
} catch (InterruptedException e) {
Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
};
thread.start();
This simple code is giving run time error. Even If I take out the while loop, it is still not working.
Please, can any one tell me what mistake I am doing. Apparently, I copied this code directly from an e-book. It is suppose to work but its not.
Android commandment: thou shall not interact with UI objects from your own threads
Wrap your Toast Display into runOnUIThread(new Runnable() { });
Example of new thread creation taken from Android samples (android-8\SampleSyncAdapter\src\com\example\android\samplesync\client\NetworkUtilities.java):
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
runnable is the Runnable that contains your Network operations.
You can use HandlerThread and post to it, here is an example to service that has one.
public class NetworkService extends Service {
private HandlerThread mHandlerThread;
private Handler mHandler;
private final IBinder mBinder = new MyLocalBinder();
#Override
public void onCreate() {
super.onCreate();
mHandlerThread = new HandlerThread("LocalServiceThread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
}
public void postRunnable(Runnable runnable) {
mHandler.post(runnable);
}
public class MyLocalBinder extends Binder {
public NetworkService getService() {
return NetworkService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
You may define your jobs in a runnable object, use a thread object for running it and start this thread in your service's onStartCommand() function. Here is my notes:
In your service class:
define your main loop in an Runnable object
create Thread object with the runnable object as parameter
In your service class's onStartCommand method():
call thread object's start function()
my code :
private Runnable busyLoop = new Runnable() {
public void run() {
int count = 1;
while(true) {
count ++;
try {
Thread.sleep(100);
} catch (Exception ex) {
;
}
ConvertService.running.sendNotification("busyLoop" + count);
}
}
};
public int onStartCommand(Intent intent, int flags, int startId) {
sendNotification("onStartCommand");
if (! t.isAlive()) {
t.start();
}
return START_STICKY;
}