FLAG_KEEP_SCREEN_ON working in reverse - android

This is an odd one.
I was previously using:
android:keepScreenOn="true"
in my layout file to keep the screen on in an activity and this worked fine.
However I wanted to improve the so that the screen is only kept on when the web app is in a particular state. (The user should still be able to turn the screen off if they wish, I effectively just want to disable the timeout - which the above in the layout file achieves whenever the activity is active.)
To do this I have a JavaScript interface add to the WebView which casks the following two methods.
I have commented out the keepScreenOn setting in the layout.
#JavascriptInterface
public void keepScreenOn(){
Toast.makeText(mContext, "Keeping screen on", Toast.LENGTH_LONG).show();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#JavascriptInterface
public void allowScreenOff(){
Toast.makeText(mContext, "Allowing screen off", Toast.LENGTH_LONG).show();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
Now the correct Toast is displayed, but the "keep screen on" action is reversed.
i.e. when I get the Toast saying the screen will be kept on it times out and switches of after a couple of minutes. BUT when I get the Toast saying that the screen will be allowed to turn off the screen actually stays on without ever timing out.
I don't understand how this can be.
OK, the plot thickens.
It seems it may not always be a reversal of the operation, but could be a random work/not working situation.
Also, looking in the log in Android Studio, I'm getting an error that says:
01-26 20:22:51.358 2182-5629/com.nooriginalthought.bluebadgeparking E/ViewRootImpl: com.nooriginalthought.bluebadgeparking.websiteViewActivity : Only the original thread that created a view hierarchy can touch its views.
when the method is called.
BUT it does work sometimes.
The methods shown above are within the websiteViewActivity class, but are not within the onCreate method. I'm afraid I don't know if this is relevant or how to ensure the addFlags and clearFlags are run in the correct thread if it is relevant.
[Edit: This question explains how to get things running on the UI thread and has got rid of the 'Only the original thread' error.]
And why does it sometimes work (I can't say if the error show up in the log when it works or not as I've only seen it working when testing away from my PC)?

The text "Only the original thread that created a view hierarchy can touch its views" means that you are executing this code from non-main thread, which is also called a UI Thread.
The WebView usually executes javascript in a background thread so that's why you get this error.
Try using "runOnUiThread()"
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(mContext, "Keeping screen on", Toast.LENGTH_LONG).show();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
});

private Window wind;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//your code
wind = this.getWindow();
wind.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
wind.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
wind.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
wind.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}

Related

Android code does not seem to run synchronously

I would like to know why my Android code is not running Synchronously.
I am overriding Cordova's Mainactivity class's onCreate to execute custom code when the app starts.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1. Show loading dialog
Display display = getWindowManager().getDefaultDisplay();
Dialog loadingDialog = Loading.createLoadingDialog(this, display, getLoadingHTMLPath());
loadingDialog.show();
loadUrl(launchUrl);
// 2. Copy bunch of files (this takes some time)
copyFiles();
}
I am expecting the app to show the loading dialog first, and then copy the files. However, I see a black screen on the app launch. Then the app copies all the files. It is only after that the app displays the loading dialog.
Why is second part of the code running first? Any suggestions on how to get the dialog to display first?
Edit
This was my initial solution that worked.
Thread onAppStartTask = new Thread(new Runnable() {
public void run() {
copyFiles();
}
});
onAppStartTask.start();
Well, the thing is, you are running the code synchronously. That's the problem. Android has exactly one thread for displaying and modifying the UI, so the call to copyFiles() will prevent any further action in the UI until it finishes.
The show() call doesn't occur instantaneously - onStart() and onResume() need to be called first - and the screen turns black because it's not able to draw anything while your app is stuck in onCreate(). The highly recommended solution is putting the file-loading logic in a background thread and periodically updating the ui with its progress.
Try this for starters and see if it works.
cordovaInterface.getThreadPool().execute(new Runnable() {
#Override
public void run() {
copyFiles();
}
}

Loading huge XML layout in Activity, causing freeze when device locked and unlocked when activity is in front?

I have loaded a huge layout XML ( > 1600 lines ) which has a view flipper with multiple layouts. It was first freezing at 'onCreate' but I changed to code to inflate the layout in background and pass the returned view to 'setContentView' at 'onPostExecute'. (This is working fine)
Now, when the activity is open (is in front) and the device is locked (or screen turned off), when I try to unlock the device, it freezes completely on some devices, and on other devices it shows a dialog saying "App isn't responding. Do you want to close it?" with options to "Wait" and "Ok".
Please help me to fix this issue.
Thanks
I finally figured out, what was causing the trouble.
I was using the LayoutInflater in an AsyncTask to inflate the whole XML into a View, like this...
#Override
protected View doInBackground(Void... params) {
Looper.prepare();
View view = getLayoutInflater().inflate(R.layout.my_large_xml, null, false);
return view;
}
#Override
protected void onPostExecute(Void result)
{
setContentView(view);
}
It turns out, that, when we set the content view using the view object, it freezes the device when activity is paused (I am not sure why).
But when I use the method setContentView(R.layout.my_large_xml) , it works perfectly fine. So I dropped the idea of loading the XML in background, and now I am doing it on my main thread in the conventional way, because we cannot call setContentView from another thread.
Sad ! Its not how I wanted it to be, as it freezes the app when the setContentView is called initially, but at least its working now. :(
I will not give up, and keep trying. And, in case if I find any better solution, I will update the answer. :)

Show toast with Application context before Activity appears

Inside onCreate of Application class, I set its instance to a static field, then show all application Toasts through this context. All works good except one thing, in some places a Toast can be shown before first activity can even appear but Toast never appears or sometimes just flashes. I think its because Activity not shown or drawn yet ? Or I'm missing something.
Edit:
More like showing toast from onCreate of Application class
Edit 2 :
public class TestApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Test from App", Toast.LENGTH_LONG).show();
}
}
If you want to show a Toast without the application even started manually by the user you can register a BroadcastReceiver which listens to the BOOT_COMPLETED system broadcast and then start a Service which will handle your Toasts.
You'll find many examples on how to do this.
To make a Toast before drawing your layout resources, just do this following.
//put this code before your setContentView(R.layout.your_layout);
Toast.makeText(yourclassName.this,"your text here",5000).show();
Well, consider one thing. If you want this toast to be shown before loading your activity and notify users some message. Then it might not be possible always. Because, The time Toast is shown with fraction of nano/mili seconds your layout is being loaded as-well.Moreover, scenario is totally different when you are on a real device and on a emulator.This might be the cause you got a flash of your Toast message. Just run it on a real device and you will see the differences.
Hope that helps

increase sensitivity to user touch

I have a custom table layout where each row is a slide-able view. Everything is working fine, except there is a continuous delay between when a user starts sliding a when the view starts moving. Is there a way to reduce that starting delay?
I am building my table layout inside an async task. So at first I was getting an error about needing to use a looper. Since I didn't know how to do that I use runOnUiThread to handle the problem code. So now I am wondering if that's the reason for the slow response to touch. Here is the code
activity.runOnUiThread(new Runnable() {
public void run() {
handler.post(mResizeViews);
}
});
The question may be "What happen when user sliding?"
if you do some heavily task such as inflate layout when user start slide.
So, check what happen when user start sliding

Opening WebView in background

This is the first time I ask something, so if there is something wrong just tell me and I´ll try to fix it ASAP.
We have a customer that wants us to login in their servers with a native Android app, but without giving us a custom way to do this. They want us to use the current website they have to log and, after authentication takes place, retrieve within the browser a XML which contains the data we need. After that, use the data in the native app. All of this with the user not knowing/seeing that a browser is being used. A total mess IMHO.
Of course, I have never tried this approach in the past and my first tests make me feel like this is impossible (or extremely difficult) to achieve. Whenever I try to load the URL in a hidden WebView the default browser pops up showing the website.
My main question is, is it possible to load a webview and work with it (invoke javascript, etc...) in the background?
Thank you.
You could set the WebView to hidden by default with the attribute android:visibility="gone", interact with it at runtime then when you need to show it to the user after you've loaded data, just call setVisibility(View.VISIBLE)
Hope this helps!
Ofc, you must to use a Thread :
protected void getPage(){
Thread th = new Thread(){
public void run(){
//Download and make things
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
//print int the activity
}
});
}
};
th.start();
Remember, and thats is VERY important, you CANT draw from thread to the main activity. The only who can draw in the screen is the main activity. You can draw with 2 methods:
One , with the method _mActivity.runOnUiThread(new Runnable() {_ like the example i put.
Two, use a Handler to send messages from thread to main activity with the information that you want to draw.
*Main activity is the activity that its in the screen in that moment, not the first activity of the app

Categories

Resources