Intent Service blocking the UI - android

I need to make so backround job without blocking user UI, so I made a test IntentService to check how it's work, but this intent services block the UI.
Here my Code on start app ic start service:
Intent msgIntent = new Intent(this, AutoExchange.class);
startService(msgIntent);
AutoExchange.java
public class AutoExchange extends IntentService{
public AutoExchange() {
super("AutoExchange");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The problem is that this service block the main Ui, somethig I did wrong?

instead of thread.sleep() you can you handler
here is an example
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// do stuff
}
},3000);

Try to make a new Runnable() around the try-catch-block.
Caution: A service runs in the main thread of its hosting process; the service does not create its own thread and does not run in a separate process unless you specify otherwise.
Source

Register your service in android manifest.

Related

Avoid ANR on SCREEN_ON using Handler Thread

Getting ANR executing a blocking/heavy call for Intent.ACTION_SCREEN_ON. Below is the code
private static BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_ON)) {
// Blocking operation
}
}
}
To avoid ANR, I am planning to move the Blocking operation inside worker thread. Will the below code help in avoiding the ANR?
private static BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_ON)) {
new Handler().post(new Runnable() {
#Override
public void run() {
//Blocking operation
}
});
}
}
}
No. BroadcastReceivers are short-lived. There is no guarantee that the OS process hosting your BroadcastReceiver will live long enough to execute this code. Not only that, but you would be running this code on the Main (UI) thread, which you cannot block (your Runnable will not run in a "worker thread", it will run in the Main (UI) thread).
Your BroadcastReceiver should start a Service, which can run a background (worker) thread which can perform your blocking operation. Or you may be able to use JobScheduler to schedule this operation (if it is suitable for your purpose).

Intent from executors for reciever is not sent

I can’t catch up - how to send Toast from Executors.newSingleThreadExecutor () in the run () method? In the debug I set a breakpoint, everything is fine, we go into the method, but the message does not appear in the emulator? And yet, in the same method, I send the intent to the receiver, the intent is sent, but the receiver does not receive it.
ExecutorService service:
public void start() {
service = Executors.newSingleThreadExecutor();
service.submit(new Runnable() {
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Intent intent = new Intent(ACTION_FOR_FRAGMENT);
sendBroadcast(intent);
service.shutdown();
}
});
}
I solved this problem, you can close the question. The essence of the problem was that I did not correctly implement the service methods.

Run volley request every 5 minutes in background android

I use Volley library to connect with server in my app. Now, I have to send request in background every 5 minutes also when app is not running (killed by user). How should I do it? With background services, AlarmManager (Google says that it isn't good choice for network operations) or something else?
Or maybe SyncAdapter will be good for it?
You can use a TimerTask with scheduleAtFixedRate in a service class to achieve this, here is an example of Service class, you can use it
public class ScheduledService extends Service
{
private Timer timer = new Timer();
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
sendRequestToServer(); //Your code here
}
}, 0, 5*60*1000);//5 Minutes
}
#Override
public void onDestroy()
{
super.onDestroy();
}
}
You can use sendRequestToServer method to connect with the server.
Here is the manifest declaration of the Service.
<service android:name=".ScheduledService" android:icon="#drawable/icon" android:label="#string/app_name" android:enabled="true"/>
To start the service from MainActivity,
// use this to start and trigger a service
Intent i= new Intent(context, ScheduledService.class);
context.startService(i);
I prefer to use Android Handler because it is executes in UI Thread by default.
import android.os.Handler;
// Create the Handler object (on the main thread by default)
Handler handler = new Handler();
// Define the code block to be executed
private Runnable runnableCode = new Runnable() {
#Override
public void run() {
sendVolleyRequestToServer(); // Volley Request
// Repeat this the same runnable code block again another 2 seconds
handler.postDelayed(runnableCode, 2000);
}
};
// Start the initial runnable task by posting through the handler
handler.post(runnableCode);

app forceclose while running in background

In my android app i have one service which calls some webservices after a fix interval.
App is running perfectly in foreground and refresh data,but when user exit from app and use some other app then my app force close after many times.
Why this app force close while running in background.
Code that i was using for start service -
msgIntent = new Intent(mContext, MyBackgroundService.class);
startService(msgIntent);
and inside onDestroy() of my main activity i have following code to stop service-
if(msgIntent!=null){
stopService(msgIntent);
}
background service call some async task and each aync task onPostExecute() method execute some insert statement in database.
i am not geting why this force close occure.
Please give your comments.
Thanks in advance.
My Service Code
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
callAsynchronousTask();
return Service.START_NOT_STICKY;
}
#Override
public void onCreate() {
mContext = this;
super.onCreate();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
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 {
callWebservice();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
};
timer.schedule(doAsynchronousTask, START_DELAY, DELAY);
}
Actually the problem is here
if(msgIntent!=null){
stopService(msgIntent);
}
in your onDestroy(). Because when you close your application so this above code gets called which is closing your service.
And after closing service again you are trying to insert data by calling service + web service. Hence, there is no service object thats why it gets crashed.
To handle this scenario, you need to comment above code which is in onDestroy() & then check/run it, will solve your problem. & there you need to stop your service by other ways. Go step by step.
you stop the service at onDestroy() method. but services are not depend the activity. So try to neglect the stop service.
(or)
try
{
//stop service code
}
catch(Exception e)
{
}
try this.

how to stop Handler working in android?

My APP has to start some time consuming job when receiving ACTION_SCREEN_OFF, and interrupt the job when receiving ACTION_SCREEN_ON if job is still going on.
public class TimeConsumingWorkIntentService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
TimeConsumingWork();
}
}
public class ScreenStatusReceiver extends BroadcastReceiver {
Intent intent = new Intent(mContext, TimeConsumingWorkIntentService.class);
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
mContext.startService(intent );
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
mContext.stopService(intent );
}
}
}
By print log of time, I find time consuming work is still going on stop the TimeConsumingWorkIntentService (when receiving ACTION_SCREEN_ON).
why ?
Use
// Cancel the runnable
myHandler.removeCallbacks(yourRunnable);
Ok , then you can do something like this
Runnable r = new Runnable{
public void run(){
if(booleanCancelMember != false){
// within this you make the call to handler and work
// Since you block the call the handler wont get repeated
}
}
}
You can't do this like that. When you start your IntentService, it will call onHandleIntent() on a separate worker thread. That mehod then calls TimeConsumingWork(). Stopping the service will not interrupt the execution of the worker thread. It just tells the worker thread that when it has finished processing the current Intent, it should stop.
What you will need to do is to have your TimeConsumingWork() method periodically look to see if it should stop. You can do this by setting a static boolean variable and have TimeConsumingWork() periodically check this variable and quit if it is set.
You don't need to call stopService() on an IntentService as it will stop itself when it has nothing to do.

Categories

Resources