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
Related
Given a one-activity app like this:
public class MyActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
loadingScreen = new RelativeLayout(this);
// add a bitmap to loadingScreen
setContentView(loadingScreen);
Dict dict = new Dict();
dict.init();
// this method takes ~10 seconds
}
}
In theory, it looks like this would display a loading screen while the dictionary initializes. In practice, nothing is displayed until onCreate() returns, so the user sees a blank white screen for 10 seconds. What's the best way to display a please wait while this app loads screen?
I believe I could create a separate thread for dict.init(), but that seems like overkill in this case because I don't want the app to be usable or interactive while dict.init() runs. I'd like it to run on the main thread (and hang the rest of the app while it executes), I just want to display something on the screen first.
PS, I tried moving dict.init() to onStart(), that appeared to have no effect.
edit: Perhaps I should have clarified this to avoid getting "You're doing it wrong" type answers, but the init takes 2 or 3 seconds on modern phones and tables, 10 seconds is a worst-case on old phones. This app is a word game, it can't be used without the dictionary. Moving dict.init() to an async task will not improve the user's experience, and the question I asked is whether it's possible to display a splash screen without doing that. I gather that the answer is "No."
I'd like it to run on the main thread (and hang the rest of the app while it executes)
No, no wouldn't and your users wouldn't like you much either
I believe I could create a separate thread for dict.init(), but that seems like overkill in this case because I don't want the app to be usable or interactive while dict.init() runs.
This is exactly what you should do. You can use a variety of ways including an AsyncTask
and show a ProgressDialog while the work is being done.
so the user sees a blank white screen for 10 seconds.
If it is taking this long then you might want to rethink your flow. Even if you go with a separate Thread and show a ProgressBar, most users aren't going to want to stare at that for 10 seconds. You should load the data in the background and allow them to do something else while it loads, if possible. You could use something like an IntentService depending on how you are getting the data.
Example of AsyncTask
Painless Threading
So, kind of a noob situation, but today, out of curiosity, I tried to do something like:
new Activity().runOnUiThread( new Runnable{...})
mostly because i don't actually have access to any activities (working on a 3rd party library). I just have the applicationContext, which i don't think allows me to make that runOnUiThread call.
So i guess i'm kind of wondering if there is a way to somehow fake out a minimally-invasive activity just so i can run something on the UI thread (or do other things, like pop up dialog...etc.) ??
if not, does anyone know what's wrong with just making new Activity() ? ( i mean, aside from the fact that, yes, i will get a null pointer because i haven't set my base context since the onCreate for the activity never got called ). if possible, i would like to accept an answer that can provide a little more detail and more "context" (no pun intended)
new Handler(context.getMainLooper()).post(new Runnable()
{
#Override
public void run()
{
}
});
Activity is managed by Android OS and is not meant to be used this way, to do so would mean breaking the API contract so don't expect it to behave correctly.
If you want to show some dialog, just create an Activity with transparent background, to the user it would be the same as a single Dialog floating above another screen.
I stack with this, I'm trying to create application using TabLayout. I have 3 tabs (3 different activities). I also got service which reads my gps position - that works fine. I got thread which post to the web server user position - that works to.
Now I'm trying to create thread which ask web server if there are any messages for user. If there are - thread try to show custom dialog (2 text views and gallery - it works if i start action from activity by clicking button), and there problem starts I know i can't update UI form threads different from main thread but i don't know how to work around this. I tried to use AsyncTask - failed - i don't want to assign AsyncTask to specific Activity as inner private class.
I wish I could show my custom dialog regardless of the tab on which user is currently using.
Thread works fine, but how to show that dialog.
I read about runOnUIThread but don't know how to use it.
Any ideas, any similar examples ??
Using runOnUiThread is easy.
YourActivity.this.runOnUiThread(new Runnable() {
public void run() {
YourActivity.this.showDialog(CUSTOM_DIALOG_ID);
}
}
You need to use a Handler. http://developer.android.com/reference/android/os/Handler.html
I have a problem that causes me some problems when a user (or another app, like the phone-application) pushes my application to the background.
My application does following:
A User can enter some information that is supposed to be pushed to a server.
When the user clicks "Send" i open a managed ProgressDialog and start an AsyncTask that performs the server communication.
When server communication is complete the AsyncTask reports back to my Activity where i perform a dismissDialog().
Directly after dismissDialog(), I will show another managed dialog using showDialog() that will inform the user about whether the submission was ok or if it failed.
This all works perfectly without any issues; however, when a call happens to come while the AsyncTask is running I get (seemingly random) one of these results:
The activity holding the managed dialog is dismissed completely and the previous view from the stack is presented when I come back.
The activity holding the managed dialog is still on screen, but it is grayed out without showing a dialog. The only way to fix this is to rotate the phone at which point it shows the "Submission sent"-dialog exactly the way it should and everything is ok after that.
All this happens without any warning messages so I get absolutely no clues as to why Android is behaving this way.
I know a way around this and that is to cancel the AsyncTask (so no dialogs are shown at the end). However, in this very use-case the requirements are that the app has to try to complete the server transaction so that there is as little confusion as possible (i.e. the user wondering if it was really sent or not).
Has anybody else had this issue and knows a way around?
I see recommendations to hold a reference to the asynch task in onRetainNonConfigurationInstance
What to do with AsyncTask in onPause()?
Or implement a bus:
https://github.com/commonsguy/cwac-bus/tree
EDIT: The complexity of your challenge is two fold:
1) saving and restoring state of your app on a kill such as when there is an incoming phone call
https://sites.google.com/site/jalcomputing/home/mac-osx-android-programming-tutorial/saving-instance-state
2) somehow continuing the asyncTask on kill instead of canceling it onPause
https://sites.google.com/site/jalcomputing/home/mac-osx-android-programming-tutorial/asynch
Both of these are significant challenges alone, and trying to fix both at the same time would give me a headache. In fact, I am getting a headache just thinking on it :) One clue is that you say the dialog returns on orientation change. This MAY be due to the fact that using the standard architecture for dialogs, the OS handles saving and restoring the state of dialogs for you on orientation change.
[EDIT] See CommonsWare
#Override
public Object onRetainNonConfigurationInstance() {
task.detach();
return(task);
}
and
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bar=(ProgressBar)findViewById(R.id.progress);
task=(RotationAwareTask)getLastNonConfigurationInstance();
if (task==null) {
task=new RotationAwareTask(this);
task.execute();
}
else {
task.attach(this);
updateProgress(task.getProgress());
if (task.getProgress()>=100) {
markAsDone();
}
}
}
where task is an instance of
static class RotationAwareTask extends AsyncTask<Void, Void, Void> {
I see no reason why this would not work for all types of soft kills, but on a hard kill, well, you get killed. Dead is dead :)
Without looking at your code it is slightly difficult to say what the problem is. However, here is something you could use to help get around the problem. You can override the onPause() method of your Activity.
This is taken directly from the Android Acitivy javadoc:
onPause() is where you deal with the user leaving your activity. Most importantly, any changes made by the user should at this point be committed (usually to the ContentProvider holding the data)
I read a lot about handling rotation in android applications, but I still have so many questions and need to much to understand.
Let me explain my problem or implementation, that I'm using now in my application.
If an activity will be opened, a get request will be sent to server. This request will be executed in a Thread (new Thread(...)) and if request was completed, activity's ui will be refreshed.
But what should I do, if the user rotate his device?
By default, the activity will be destroyed and request will be started again and start a new thread, but the thread of destroyed activity may be still running.
I guess, it's a quite wrong way, I have now.
But what is the best approach, to handle this?
Probably is the best way to forbid rotation, but what If I don't want that?!
May be it's the second part of my question:
I saw a video form Google IO. Mr. Dobjanschi suggested to use services and to store retrieved data in content provider. So, probably I can use a service for executing my requests. But should data be replaced every time the get request was completed?!
Well dont know exactly how its done, You can try saving the instance and retrieving the same when config changes with following methods:
I have read about them but haven't really implemented them yet. I hope it can give you some start.
#Override
public Object onRetainNonConfigurationInstance() {
return(myServerThread);
}
private void restoreServerFunctions() {
if (getLastNonConfigurationInstance()!=null) {
myServerThread=(Thread)getLastNonConfigurationInstance();
}
}
You can specify that the activity handles the rotation itself. This is done through adding:
android:configChanges="keyboardHidden|orientation"
in the tag of the activity inside your android manifest. You don't have to actually handle the rotation but this will tell android to not destroy your activity. The base activity class will handle all the rotating of the user interface for you and your thread will be executed correct.
A small side note: if you are doing only a small server task use AsyncTask to execute the call to the server in the background instead of creating a thread. This will minimze some of the programming effort you need to communicate the results from the thread to the activity and update your UI.
One easy way, though I've never tried it. Instead of refreshing the current UI, when the thread finishes, start a new Activity with the just downloaded content. So first, you start an Activity with a blank page (or just the page's frame), then you rotate the blank page as much as you like, then the downloading Thread spawns a new Activity, replacing the blank page Activity with the loaded content page using the current orientation.