I'm developing an Android application and for some reason that has not yet been identified at random times it minimizes itself. I want to use the onPause callback function that is called when the app is minimized to programmatically reopen it.
As already mentioned, being able to make a rule to call the application reopening after a while so that it is not reopened immediately using Timer and TimerTask and a Boolean key:
private Timer mActivityTransitionTimer;
private TimerTask mActivityTransitionTimerTask;
public boolean wasInBackground;
private final long MAX_ACTIVITY_TRANSITION_TIME_MS = 3000;
#Override
protected void onPause() {
super.onPause();
System.out.println("debug Pause/Resume: --- P A U S E ----");
startActivityTransitionTimer();
}
#Override
protected void onResume() {
super.onResume();
System.out.println("debug Pause/Resume: ---- R E S U M E ---");
stopActivityTransitionTimer();
}
public void stopActivityTransitionTimer() {
if (this.mActivityTransitionTimerTask != null) {
this.mActivityTransitionTimerTask.cancel();
}
if (this.mActivityTransitionTimer != null) {
this.mActivityTransitionTimer.cancel();
}
this.wasInBackground = false;
}
public void startActivityTransitionTimer() {
this.mActivityTransitionTimer = new Timer();
this.mActivityTransitionTimerTask = new TimerTask() {
public void run() {
wasInBackground = true;
System.out.println("debug Pause/Resume: --- NEED REOPENE --");
}
};
this.mActivityTransitionTimer.schedule(
mActivityTransitionTimerTask,
MAX_ACTIVITY_TRANSITION_TIME_MS
);
}
I need to replace NEED REOPEN log with something that makes the app reopen.
I have already tried:
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("package");
if (launchIntent != null) {
startActivity(launchIntent);//null pointer check in case package name was not found
}
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("package","package.Activity"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Nothing worked, I'm inside an activity
Related
I have trouble ending an AsyncTask, even though IMHO, I have adhered to the recommended flagging practice. The code below only takes the BackButton into account, but to have a general solution for all kinds of exiting the activity would be best.
I have a MeasurementLoadingsScreen Class which binds a Service like this:
ServiceConnection _connection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
_service = myService.Stub.asInterface(iBinder);
runMeasurementAsyncTask();
}
public void onServiceDisconnected(ComponentName componentName) {
_service = null;
}
};
#Override
protected void onStart() {
super.onStart();
Intent serviceIntent = new Intent();
serviceIntent.setPackage(myService.class.getPackage().getName());
serviceIntent.setAction(myService.class.getName() + ".ACTION_BIND");
bindService(serviceIntent, _connection, BIND_AUTO_CREATE);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_measurement_loadingscreen);
findViewsById();
setDefaultVisibility();
intent = getIntent();
//myStuff
}
The MeasurementLoadingScreen contains an AsyncTask with a WeakReference (or SoftReference, tried both).
private void runMeasurementAsyncTask() {
//myStuff
meTask = new MeasurementTask(this);
meTask.execute();
}
private static class MeasurementTask extends AsyncTask<Integer, Integer, String> {
private WeakReference<MeasurementLoadingScreen> activityReference;
private ServiceHelper serviceHelper;
//myStuff
public static boolean isRunning = false;
MeasurementTask(MeasurementLoadingScreen context) {
activityReference = new WeakReference<>(context);
serviceHelper = new ServiceHelper(context._service);
}
#Override
protected String doInBackground(Integer... params) {
MeasurementLoadingScreen activityReference = this.activityReference.get();
isRunning = true;
//myStuff, it's ok to finish running this before cancelling
if (isCancelled()) {
return "cancelled";
}
// more myStuff
if (isCancelled()) {
return "cancelled";
}
[...]
#Override
protected void onCancelled(){
//myStuff: safely shutdown measurement process, might take a few seconds at worst
meTask.isRunning = false;
if(activityReference.get() != null) {
activityReference.get().finish(); //it does not work without this, either
}
super.onCancelled();
}
When I tap back twice (regardless of specific behaviour), it should (safely) abort the AsyncTask:
#Override
public void onBackPressed()
{
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
if (meTask == null) {
super.onBackPressed();
return;
}
cancelTask();
Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
return;
}
else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }
mBackPressed = System.currentTimeMillis();
}
#Override
protected void onStop() {
super.onStop();
if (_connection != null)
unbindService(_connection);
finish();//
}
#Override
public void onPause() {
int i = 0;
super.onPause();
//poll state of task here
finish();
}
I cannot seem to get the Task to stop running. If I set the meTask =null; in onPause, for example, it will eventually go through onCancelled and then call onStop, ending the service as well. But there is no way of waiting for the onCancelled to do its stuff and notify me with the isRunningflag, getStatus or whatever. The app just freezes however I poll the Task, which stays RUNNING all the time, unless I set it to null (undesirable, of course).
Edit:
I have added a polling attempt that allows the activity to call onPause/onStop eventually, but my main issue is with the polling, I do not ever see a finished/finishing task, even though onCancelled gets called at some point, but only after I set the meTask = null;, it does not continue cancelling normally.
public void onBackPressed() {
int i=0;
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
if (meTask == null) {
super.onBackPressed();
return;
}
cancelTask();
Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
while ((meTask.getStatus()== AsyncTask.Status.RUNNING) && (i < 20000)) {
//waiting etc., checking für isRunning doesn't work either
i++;
}
Log.d(TAG, "meTask " + meTask.getStatus());
meTask = null;
Log.d(TAG, "meTask null after " + i);
super.onBackPressed();
return;
Edit 2:
Content of cancelTask()
private void cancelTask() {
if (meTask != null) {
Log.d(TAG, "Async Task Cancel... ");
meTask.cancel(true);
}
}
Edit 3:
Regardless of where I put the cancel(true), e.g. onPause, onStop, the Task stays alive and only gives me the Log output of
if (isCancelled()) {
Log.d(TAG, "Cancel after XYZ");
return "cancelled";
}
and
#Override
protected void onCancelled() {
super.onCancelled();
isRunning = false;
Log.d(TAG, "...Async Task Cancelled ");
}
at the very end, after onPause, onStop, onDestroy have finished. I am at my wits end. It is not surprising that the Task continues to run for a bit, but it must stop before the service in unbound. How can I wait for the task to finish?
I am developing a android app, which will update device location after 4 seconds interval and depending on the response received from the server it will open specific activity.
Problem 1) In some case it will open up a activity like incoming phone call with sound. I am facing problem when I am removing the app from recent app. I noticed the poll function is running twice at the same time, and multiple media is playing at the same time.
Problem 2) I am using Service intead of IntentService(I am a beginner and not sure which will be better). The background service should run even the phone goes to sleep mode, just like WhatsApp or other messenger run.
As the file is big enough, I am attaching only important part
public class TaxiNorrService extends Service implements LocationListener {
...
...
final Handler poll_handler = new Handler();
private NotificationManager mNM;
private final Actions actions = new Actions();
public Ringtone r;
private String newtext;
private Runnable BreakRunnable;
private Runnable poll_runnable;
private Handler BreakHandler;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
poll_runnable = new Runnable() {
#Override
public void run() {
if(!App.isAutoBreak()){
if(BreakHandler !=null){
BreakHandler.removeCallbacks(BreakRunnable);
}
if(r != null) {
if (r.isPlaying()) {
r.stop();
}
}
}
if (actions.checkPermission(getApplicationContext())) {
checkGPS();
if(isNetworkAvailable()){
if(App.isPollOn()){
poll(latitude, longitude);
}
}else{
if(BreakHandler !=null){
BreakHandler.removeCallbacks(BreakRunnable);
}
boolean foregroud = false;
try {
foregroud = new ForegroundCheckTask().execute(getApplication()).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
boolean background = isMyServiceRunning(TaxiNorrService.class);
if(foregroud == true && background == true && App.isAppForground()){
if(!App.isLoadingVisible()){
Intent intent = new Intent(TaxiNorrService.this, Loading_activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
}
}
poll_handler.postDelayed(this, 4000);
}
};
return Service.START_STICKY;
}
private void poll(double lat, double lon){
//Connected to API endpoint
}
...
...
#Override
public void onDestroy() {
if(r != null) {
if (r.isPlaying()) {
r.stop();
}
}
poll_handler.removeCallbacks(poll_runnable);
super.onDestroy();
}
}
I found the answer for my questions. The code written in the onStartCommand should be within onCreate function. This is because onCreate will execute when service starts first time, and onStartCommand will execute every time when you start the app. Please follow this topic,
Android - running a method periodically using postDelayed() call
Hi just a newbie with android. I am trying to create a service which will constantly fetch location and update the an activity exp: Dashboard map. I have been following Android service
Now my problem is how to
- Constantly notify Dashboard activity ( was trying to simulate with while loop to notify data) from service
- I was able to print logs on connect and onBind, but i was wondering how to constantly watch for notification from service and retrieve the notified data from the Activity ie.Dashboard. Hope I am able convey my issue. I am searching for the latest api.
You should use BroadcastReceiver in your Dashboard activity. to do this follow this step:
Add a inner class to Dashboard activity like this:
public class ActionCompleteReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String state = "disconnected";
if(intent != null)
state = intent.getStringExtra("State");
//Your Code
}
}
Add this code to Dashboard activity:
private ActionCompleteReceiver mActionReceiver;
public static final String ACTION_SERVICE_COMPLETE = "YUOR_PACKAGE_NAME.ACTION_SERVICE_COMPLETE";
Register receiver in onResume method in Dashboard activity like this
#Override
protected void onResume()
{
super.onResume();
if(mActionReceiver = null)
mActionReceiver= new ActionCompleteReceiver();
registerReceiver(mActionReceiver, new IntentFilter(ACTION_SERVICE_COMPLETE));
}
Unregister receiver onPause and onDestroy:
#Override
protected void onPause()
{
super.onPause();
if (mActionReceiver != null)
{
try
{
unregisterReceiver(mActionReceiver );
}
catch (Exception ignored)
{
}
}
}
#Override
public void onDestroy()
{
super.onDestroy();
if (mActionReceiver != null)
{
try
{
unregisterReceiver(mActionReceiver );
}
catch (Exception ignored)
{
}
}
}
In your service where you need to notify Dashboard activity add this:
Intent intent = new Intent(DashboardActivity.ACTION_SERVICE_COMPLETE);
intent.putExtra("State", "Connected");
sendBroadcast(intent);
Every time I`m trying to finish an activity inside of a timer method, the activity comes back alive over and over again.
I running this activity:
public class PlayerNoAdmin extends ActionBarActivity {
Timer myTimer; boolean isAdmin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player_no_admin);
Intent oldIntent = getIntent();
if (oldIntent != null && oldIntent.hasExtra("THE_LIST")){
songs = oldIntent.getParcelableArrayListExtra("THE_LIST");
id = oldIntent.getIntExtra("ID",0);
listId = oldIntent.getIntExtra("LIST_ID",0);
isAdmin = oldIntent.getBooleanExtra("IS_ADMIN",false);
}
//update the list every k seconds
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, k_time2Update);
}
private void TimerMethod() {
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//Here check for update in the list every 30 seconds and send the new location
String url = getRunUrl();
new TaskMusicPlay().execute(url);
}
};
private class TaskMusicPlay extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String jsonResult = null;
try {
String url = params[0];
TestMain client = new TestMain();
jsonResult = client.doGetRequest(url);
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
#Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
checkIfNew(aVoid);
}
private void checkIfNew(String result) {
try {
JSONObject object = new JSONObject(result);
String temp = object.getJSONObject("info").getString("isAdmin");
isAdmin = (temp.equals("true"));
if (isAdmin) {
Intent intent = new Intent(getApplication(),YouTubePlayer.class);
intent.putExtra("THE_LIST", songs);
intent.putExtra("ID", id);
intent.putExtra("LIST_ID",listId);
intent.putExtra("IS_ADMIN",isAdmin);
startActivity(intent);
finish();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
At the end, I succeeded to move to the YouTubePlayer activity, but every few seconds the app returns to the code of this activity (and then executes again the startActivity call and goes back to YouTubePlayer) and that's going on and on.
Your Timer is periodically calling the player to start over and over again.
You must make a cancel() call to the Timer if it is no longer needed so you prevent it from holding a reference for your activity and thus preventing from being removed from the backstack and GC.
http://developer.android.com/reference/java/util/Timer.html
And your Timer is not running on the same thread as it's code because the timer thread iis another Thread and the Code in the Timer is running on UI. You can check it out by adding some logs in the Timer's run method outside of the runOnUIThread() and inside of it.
I am getting the NPE while starting the service. I have just gone through the service tutorial on android developer site.
Logs are showing unable to resume activity...
#Override
protected void onResume() {
super.onResume();
CustomIntentService cis = new CustomIntentService();
Intent intent1 = new Intent(this, CustomIntentService.class);
intent1.putExtra("NUM", 1);
cis.startService(intent1);
}
My service is :
public class CustomIntentService extends IntentService {
private final static String TAG = "CustomIntentService";
public CustomIntentService() {
super("CustomIntentService");
Log.d(TAG,"out CustomIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent");
Log.d(TAG, "service num = " + intent.getIntExtra("NUM", 0));
if (Looper.getMainLooper() == Looper.myLooper()) {
Log.d(TAG, "In main ui thread");
} else {
Log.d(TAG, "In worker thread");
}
}
}
Change your code for onResume to the following:
#Override
protected void onResume() {
super.onResume();
//CustomIntentService cis = new CustomIntentService();
Intent intent1 = new Intent(this, CustomIntentService.class);
intent1.putExtra("NUM", 1);
startService(intent1);
}
This should fix the issue, remember intent knows which service to start and startService() is called on context. So here activity's instance will be the context.
Also,
Since Service is a component, so you should be declaring it in the AndroidManifestFile
<service
android:name=".CustomIntentService">
</service>
*Note: CustomIntentService should be under current directory, or you can supply absolute path also.
You can refer this