Start activity from service takes too long

Viewed 4888

I have a Service that when one function gives to me true it will start a new Activity but it takes like 5 seconds...

I've read about this issue, and I've found on StackOverflow this example to "avoid" this bug..

Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
try {
   pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
   e.printStackTrace();
}

but sadly it doesn't start the Activity faster, I don't need to be inmmediate (better if it's possible), but I don't want to wait +5 seconds to launch the new Activity, do you knwo any trick to avoid this?

I'm using PendingIntent because I've found that guy that said that it should solve this issue : Starting an activity from a service after HOME button pressed without the 5 seconds delay

Note

If I press back button it launch it autommatically, 0 delay, but I'm looking pressing the home button.

3 Answers

I cannot comment everywhere yet, so I'm putting this solution of a similar problem as an answer

After much digging, found out the cause of the problem. Apparently it's not a bug, it is a feature which does not allow Services or BroadcastReceivers to launch activities for up to 5 seconds after home button is pressed. No easy way to overcome this.

More info here: https://code.google.com/p/android/issues/detail?id=4536

I replaced the activity with a Window added to the window manager of the running service. This does not cause any delay.

Source link Stackoverflow

First thing we cannot update any UI related stuff in service, neither calling activity nor updating any UI elements, 
Same problem i too have faced.

Then i have used EventBus library to communicate UI elements from service 
Below is the sample example

public class SendSPLocationService extends Service {
Handler mHandler = new Handler();
Thread downloadThread;
boolean isRunning = true;
private VolleyHelper volleyHelper;

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void onCreate() {
    //  Toast.makeText(this, " MyService Created ", Toast.LENGTH_LONG).show();
    volleyHelper = new VolleyHelper(this);

}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    final Timer t = new Timer();
    t.schedule(new TimerTask() {
        @Override
        public void run() {
            Log.d("run: ", "service is running!");

            try {
                                        EventBus.getDefault().post(new FutureJobEvent(false, error.networkResponse.statusCode, errorJson.getString("message")));

            } catch (JSONException e) {
                e.printStackTrace();
            }
            // t.cancel();
            Log.d("run: ", "service is stopped!");

        }
    }, 0, 5000);
    return START_STICKY;
}
}

Use below code for triggered event to observe..either in activity/fragment

@Override
public void onStart() {
    super.onStart();
    if (!EventBus.getDefault().isRegistered(this))
        EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    super.onStop();
    if (EventBus.getDefault().isRegistered(this))
        EventBus.getDefault().unregister(this);
}
 @Subscribe(threadMode = ThreadMode.MAIN)
 public void onMessageEvent(TrackSPEvent event) {
    if (event.success) {
         startActivity(new Intent(this,MainActivity.class));
 }
 }

I tested with the PendingIntent approach and couldn't find anything wrong. That seems to be working fine. However, for reference, here is what I tried at my end:

public class MyService extends Service {
    public static final String SERVICE_COMMAND = "COMMAND";
    public static final String TAG = "MyService";
    public static final int SERVICE_START = 0x01;
    public static final int START_ACTIVITY = 0x02;

    private class ServiceHandler extends Handler {
        public ServiceHandler(HandlerThread thread) {
            super(thread.getLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case START_ACTIVITY:
                    Intent ActivityIntent = new Intent(getApplicationContext(), TestActivity.class);
                    ActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
                            0, ActivityIntent, 0);
                    try {
                        pendingIntent.send();
                    } catch (PendingIntent.CanceledException e) {
                        e.printStackTrace();
                    }
                    Log.e(TAG, "Service started activity -> " + System.currentTimeMillis());
                default:
                    break;
            }
            super.handleMessage(msg);
        }
    }

    private HandlerThread mThread;
    private ServiceHandler mHandler;

    public MyService() {
        mThread = new HandlerThread("ServiceThread");
        mThread.start();
        mHandler = new ServiceHandler(mThread);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int id = intent.getIntExtra(SERVICE_COMMAND, SERVICE_START);
        switch (id) {
            case START_ACTIVITY:
                Log.e(TAG, "onStartCommand Service -> " + System.currentTimeMillis());
                mHandler.sendEmptyMessage(START_ACTIVITY);
                break;
            default:
                break;
        }
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Activity Code:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "Main";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate main activity -> " + System.currentTimeMillis());
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        Intent intent = new Intent(this, MyService.class);
        startService(intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "onPause main activity -> " + System.currentTimeMillis());
        Intent intent = new Intent(this, MyService.class);
        intent.putExtra(MyService.SERVICE_COMMAND, MyService.START_ACTIVITY);
        startService(intent);
    }
}

You can try the same code at your end. May be it can help.

Related