I'm having trouble with resuming an app's activity after locking the device screen.
Here's the typical situation:
1. App is running.
2. Lock device.
3. Unlock device.
4. Instead of returning to running app, it shows a black screen.
I checked how the activity lifecycle is running and it seems this is what's happening when it unlocks:
1. Create
2. Start
3. Resume
4. Pause
Why is it stuck on pause? I'm sure this is really simple but as I'm still learning Android I'm super confused. Thanks for any help given!
EDIT:
I don't think I'm doing anything out of the ordinary but here's the basic code I'm using...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("Java", "Create");
// Initialize NDK audio properties here
// Initialize the Content View
setContentView(R.layout.activity_main);
// Setup toolbar
Toolbar myToolbar = (Toolbar) findViewById(R.id.toolBar);
setSupportActionBar(myToolbar);
// Start thread
thread = new Thread() {
public void run() {
setPriority(Thread.MAX_PRIORITY);
// Audio Thread is running here
}
};
thread.start();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onPause() {
super.onPause();
if (thread != null) {
try {
thread.join();
}
catch (InterruptedException e) {
// e.printStackTrace();
}
thread = null;
}
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onStop() {
super.onStop();
}
Try this (it will instruct your app to save state):
protected void onSaveInstanceState(Bundle icicle) {
icicle.putLong("param", 1);
super.onSaveInstanceState(icicle);
}
I am not thread expert. but here it seems you are blocking ui thread in onpause. thread.join causes the current thread(in this case ui thread) to pause execution until thread terminates.
Related
I have an android studio project. When I am rotating screen, android destroys and recreates main activity. How can I check during the destruction, if android going to recreate activity?
You can determine if the activity is finishing by user choice (user chooses to exit by pressing back for example) using isFinishing() in onDestroy.
#Override
protected void onDestroy() {
super.onDestroy();
if (isFinishing()) {
// wrap stuff up
} else {
//It's an orientation change.
}
}
Another alternative (if you're only targeting API>=11) is isChangingConfigurations.
#Override
protected void onDestroy() {
super.onDestroy();
if (isChangingConfigurations()) {
//It's an orientation change.
}
}
Override the Activity lifecycle methods to see the flow.And then use the appropriate method to check activity current state like isChangingConfigurations()
Example code snippet.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
super.onStart();
Log.i(MainActivity.class.getSimpleName(),"OnStart Called");
}
#Override
protected void onRestart() {
super.onRestart();
Log.i(MainActivity.class.getSimpleName(),"OnRestart Called");
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.i(MainActivity.class.getSimpleName(),"OnDestroy Called");
}
#Override
protected void onPause() {
super.onPause();
Log.i(MainActivity.class.getSimpleName(),"OnPause Called");
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i(MainActivity.class.getSimpleName(),"OnConfiguration Changed Called");
}
}
For more details see the official page activity-lifecycle
If the user clicks on the Home button for example, the methods onPause() and onStop() are called.
I want to call onDestroy() from the onStop() method after 1mn, unless the user goes back on the app (which calls onResume() and onStart() methods).
I tried to implement Timer:
It fails, saying it cannot call the onDestroy if Looper not implemented.
When I implement the Looper, the onDestroy() method is never called.
Maybe calling onDestroy() from onStop() is not the good thing to do, and another "clean" solution exists to get the behavior I want. I just want to kill the app after 1mn no use.
In this case, please propose.
If my wish is the good way to proceed, could you share how to implement it ?
dont call onDestroy() directly , instead call finish() after the period you want
and to support the scenario you mentioned make sure not to kill the activity if the user resumed the activity
here's a piece of code i wrote for you .
the activity will kill its self if not resumed in 1 second ;
boolean notResumed;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startActivity(new Intent(this,Main2Activity.class));
}
#Override
protected void onResume() {
super.onResume();
notResumed=false;
}
#Override
protected void onStop() {
super.onStop();
notResumed=true;
Handler handler=new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(notResumed)
finish();
}
},1000);
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d("debug","onDestroyCalled");
}
This answer is largely inspired from Abdelrahman's post above.
I just adapted few things to reinitialize the delay counter each time I go out of my app.
boolean notResumed;
//Declare my Handler in global to be used also in onResume() method
Handler myHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startActivity(new Intent(this,Main2Activity.class));
}
#Override
protected void onResume() {
super.onResume();
notResumed=false;
//Remove callbacks on the handler if it already exists
if (myHandler != null) {
//I send null here to remove all callbacks, all messages,
//and remove also the reference of the runnable
myHandler.removeCallbacks(null);
}
}
#Override
protected void onStop() {
super.onStop();
notResumed=true;
myHandler=new Handler();
myHandler.postDelayed(new Runnable() {
#Override
public void run() {
if(notResumed)
finish();
}
},10000);
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d("debug","onDestroyCalled");
}
Thanks a lot again to Abdelrahman Nazeer for its fast and accurate answer.
Please comment if something is not correctly done here. At least it works as expected...
Activity.onPause() and onStop() are called in (at least) two situations:
The another Activity was launched on top of the current one.
The app was minimized.
Is there an easy way to tell the difference?
You could do it this way. Make all of your activities extend from a base activity. The base activity needs to keep a visibility counter that is incremented/decremented during onResume/onPause:
public abstract class MyBaseActivity extends ActionBarActivity {
private static int visibility = 0;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new Handler();
}
#Override
protected void onResume() {
super.onResume();
visibility++;
handler.removeCallBacks(pauseAppRunnable);
}
#Override
protected void onPause() {
super.onPause();
visibility--;
handler.removeCallBacks(pauseAppRunnable);
// give a short delay here to account for the overhead of starting
// a new activity. Might have to tune this a bit (not tested).
handler.postDelayed(pauseAppRunnable, 100L);
}
#Override
protected void onDestroy() {
super.onDestroy();
// uncomment this if you want the app to NOT respond to invisibility
// if the user backed out of all open activities.
//handler.removeCallBacks(pauseAppRunnable);
}
private Runnable pauseAppRunnable = new Runnable() {
#Override
public void run() {
if (visibility == 0) {
// do something about it
}
}
};
}
My app shows a splash screen for 4 seconds and then opens another activity with a web view.
I am using a thread to splash the screen and finish() the first activity as soon as web view activity is started. I have also used animations like fade in and fade out.
It's CPU usage is fluctuating between 8% to 23%.What could be the reason. I want to reduce the CPU usage.
My first activity that shows splash screen and starts web view activity-
public class MainActivity extends Activity {
Thread splashThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(R.animation.fadein,R.animation.fadeout);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
//-----------------------------------------
splashThread=new Thread(){
public void run()
{
try
{
sleep(1000);
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
Intent intent = new Intent(getApplicationContext(),OpenWeb.class);
startActivity(intent);
}
}
};
splashThread.start();
//-----------------------------------------
super.onStart();
overridePendingTransition(R.animation.fadein, R.animation.fadeout);
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
finish();
super.onRestart();
}
}
Could be that you used alot of imports something like. I heard that uses alot of cpu?
import android.graphics.*
Are you using a AVD?
I have a problem, I make a simple application to show you my problem.
I want that setContentView executes and displays the .xml BEFORE the Sleep is executed. I thought everything will be execute in order?
Is there anyone how can say me why it doesn't do that?
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// do something
}
Thanks a lot!
EDIT:
Here is the real OnCreate, seems to be a bigger problem.
Everything with the sleep worked fine, but with the Connect method there are problems.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ConnectBluetooth();
}
In the ConnectBluetooth() method, I just create a new Socket and try a connection.
With a ned thread or a handler it doesn't seems to work, what should I do then? Use something like an asynctask?
Thanks a lot in common!
The layout isn't displayed until after the creation process has finished, after onResume() is called. However there is no callback for when the layout is displayed, but you can use a Handler and Runnable to do this.
Create a couple field variables:
Handler handler = new Handler();
Runnable delay = new Runnable() {
#Override
public void run() {
// Do something
}
};
And onCreate() call:
handler.postDelayed(delay, 10000);
When you call sleep, you are pausing the UI thread. This will prevent onCreate from returning, which will prevent the framework from completing initialization of your activity, including displaying your view hierarchy.
You should never pause the UI thread like that. If you want to do something after 10 seconds, you can start a separate thread that will do it at the right time:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread() {
#Override
public void run() {
try {
Thread.sleep(10000);
doSomething();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
A cleaner approach would be to use a Handler:
Handler mHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
doSomething();
}
}, 10000);
}