How can I show a progresscircle, until my whole activity did load? (Did load means, loading the activity and do some functions which need around 1-2 seconds)?
Kind Regards
You might want to look at this image to get an idea:
That's an Activity's lifecycle.
A nice way to do it would be to make the ProgressBar visible at the very start of onCreate() and make it invisible (or GONE) at the end of onResume(). Make sure you inflate the layout before accessing it though, or you'll run into errors.
(More information about Activities: Click here.)
Edit:
Maybe it's not a bad idea to use an AsyncTask for those long functions. Pass the ProgressBar to the task's constructor, then set the ProgressBar's visibility to VISIBLE in the onPreExecute function, and to GONE in the onPostExecute function.
Related
I've searched through dozens of Stackoverflow posts and the android doc but just couldn't find the answer.
According to the accepted answer of this SF-post the onCreate method runs when the activity is first created. It also notes that in here views are supposed to be created and list data is being binded.
Then the onStart Method runs but here's the issue. Where's the difference? If you do everything inside of onCreate, switch activities, your app will still display the same data, regardless whether you put the app in the background or switched activities.
So if you declare views in onCreate, what do you do in onStart? initiliaze the views to their R.id.view ? Fetch data?
onResume I suppose is then used for listeners since it's the gas and brake according to this SF-posts accepted answer.
onCreate() is called when the activity is first created. onStart() is called whenever the activity becomes visible, which includes when it is first created (after onCreate()) and after it is coming back to the screen from being stopped (e.g., another activity took over the screen).
So:
Put code in onCreate() that needs to happen when the activity is created (and use onDestroy() to clean it up)
Put code in onStart() that needs to happen either when the activity is created or when the activity returns to the foreground (and use onStop() to clean it up)
Frequently, we do not do anything special when the activity returns to the foreground, in which case you do not need to worry about onStart() or onStop().
I understand professionals use the former to tailor the onClick method to their exact specification, but cant I just use the onClick attribute and specify the same desired actions within a method.
i.e. [In xml file:] onClick="doSomething" & then
[in MainActivity.java:]
public void doSomething(View view){
//define and start intent
//Show a toast, etc
}
Why not just use the latter option? Thanks
Why not just use the latter option?
Go right ahead.
On bigger projects, it is unlikely that the activity will be managing the button directly:
You might be using fragments, in which case the fragment is more likely to manage the button than is the activity
You might be using MVP, MVVM, MVI, etc. GUI architectures, in which case some other "presenter" object is more likely to manage the button than is the activity
You might be using the data binding framework, in which case you might still be using android:onClick in a layout resource, but directing the event to something other than the activity (e.g., a fragment, a presenter)
And so on
Yes you can do so,both are doing the same thing but using the onClickListener is a better choice ,you can set the listener when you want that button to be active thus your Button and Activity are in cooordinaton.
If you use onClick in your xml file ,it will always call that method doesn't matter what is happening in your activity.
The app I'm working on shows some sensitive information that must not be shown on the "Recent Tasks" screen when stopping the app by pressing the home button.
I'd like to blur the sensitive data in the screenshot or show the app logo instead.
I am aware of the following approaches but they don't fit my requirements:
Setting the actvitie's android:excludeFromRecents to true in the manifiest prevents the app from being shown at all in the recent tasks. This would disrupt the user experience.
Using FLAG_SECURE results in a blank card on the recents tasks screen. (How do I prevent Android taking a screenshot when my app goes to the background?) I don't like the blank screen. However, I'll stick to this solution if there is no workaround.
Overriding onCreateThumbnail seems like the ideal solution but, unfortunately, doesn't work as it's currently not invoked by the OS :( (https://code.google.com/p/android/issues/detail?id=29370)
And then there are some workarounds that I tried out but that didn't work as hoped:
Start a new activity that shows the app logo in onPause so that it's screenshot is shown instead of the actual activitie's one. But the new activity takes too long to open and it disrupts the user experience.
Set the activitie's content view to an image of the app logo in onPause. That seemed like a great solution to me. Unfortunately, the screenshot for the recent tasks screen is taken at an unspecified time. During testing the app logo quickly appears before the app is closed when pressing 'Home' but the resulting screenshot shows the activity a short time before that.
Removing the sensitive data from the widgets (e.g. textView.setText("")) has the same problem of screenshot timing just mentioned.
Any alternative ideas or solutions to the listed workarounds?
I looked into this a couple of months ago for the same purpose as you.
Unfortunately, I had to conclude that it is simply not possible. I dug through the android source code and confirmed it.
There is no callbacks or methods from android that allows you to customize it (that works anyway). Besides FLAG_SECURE, this part of the code does not accept any input or change.
OnPause and similar lifecycle methods are called too late (the screenshot is taken already). All lifecycle methods that would hint that you're about to go into the background runs too late.
The image you see in the recent tasks is an actual screenshot - and thus isn't affected by changes you do (too late) to your view. That means you can't modify your view just-in-time (like making it invisible, replacing with something else, adding SECURE_FLAG, or any other obstruction of the view). As an aside, these images can be found on an emulator at /data/system_ce/0/recent_images.
The only exception is using FLAG_SECURE, which will prevent the screenshot from being taken of your application. I experimented with setting this FLAG in onPause and removing it in onResume, however as mentioned already these lifecycle methods runs after the screenshot is taken already, and thus had absolutely no effect.
As discussed in How to change the snapshot shown by recent apps list? there used to be a callback that you could use to customize the thumbnail: onCreateThumbnail. However, this does not work and it is never called. To be clear, the callback is still there, it is simply never called by the OS. The fact that it stopped working is poorly documented, but apparently was silently deprecated/removed in 4.0.3
As for the thumbnail itself, it is a screenshot taken serverside. It is taken before onPause is called (or in fact before any callbacks indicating that your activity is about to go into the background is called).
When your app does go into the background, your actual view is animated (to get that zoom-out transition). That animation can be affected through changes you do in onPause (if you're fast enough that is) (I experimented with setting opacity to 0 on the window among other things). This will however only affect the animation. When the animation is finished, the view is replaced by the screenshot taken earlier.
Also see these questions that discuss this:
When does Android take its recent apps switcher screenshot?
Show custom application image in task manager on ICS or JB
Android never call method onCreateThumbnail
Currently (28/10/2020) is impossibile customizing app thumbnail in recent apps screen.
As explained by #Dellkan in the previous answer, the onCreateThumbnail method is not called anymore by the OS.
Unfortunately, also the suggestion to create a kind of launcher/splash screen without the FLAG_SECURE flag to let the app take a screenshot of that activity is not working, because the screenshot is taken on the activity you see and not at the launch of the app.
You cannot even customize the color of window background when using FLAG_SECURE as reported here.
How about implementing a layout overlay on top of your entire activity?
Make it transparent, it's click-through by default, so no negative impact on UX while in use.
In onPause() set a half-transparent, blurred image as the background of that layout, the data will be scrambled behind it. In onResume() change the background to fully transparent again. Voila.
It might be faster than other types of overlays. The positive side effect is, if you do the unblurring as a short animation effect when the user goes back (with a proper library that uses C++ instead of Java), it might even look cool and the users wouldnt even mind seeing it.
I haven't tried this myself, but it's something you haven't tried yet.
Since onPause is called to late, I use WindowFocusChangeListener to observe when the Fragment loses focus. At this moment we can hide all view which show sensitive data:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
#Override
public void onWindowFocusChanged(boolean hasFocus) {
// hide sensitive data when window moves to background (before system screenshot is captured)
myViewWithSensitiveData.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
}
});
There is a way to customize it. You need your Activities with sensitive data to FLAG_SECURE in onCreate before you setContentView. Then you need an empty Activity, which renders whatever you want to have as the customized thumbnail. This usually is some sort of splash screen. This new Activity needs to be the launcher and is the only Activity not FLAG_SECURE. This Activity is launched and in onResume starts your actual Activity with the sensitive data.
Android OS will take a screenshot of that new Activity at the beginning of your App. Unfortunately the users will also see this Activity for a short moment. Since every other Activity is FLAG_SECURE, Android OS will use the only available screenshot it made at the beginning.
Was looking for a solution and found some dirty things in case you don't want to use 'FLAG_SECURE'. It doesn't give a nice picture but protects data and doesn't prevent making screenshots for the user while they are in the app.
protected void onPause () {
this.getWindow().getDecorView().getRootView().setScaleX((float)200);
this.getWindow().getDecorView().getRootView().setScaleY((float)200);
super.onPause();
}
protected void onResume () {
this.getWindow().getDecorView().getRootView().setScaleX((float)1);
this.getWindow().getDecorView().getRootView().setScaleY((float)1);
super.onResume();
}
I think this can only achieve through BroadCastReceiver but there is no receiver present. So therefore you first disable default screenshot functionality in android and then implementing your own functionality to take screenshot and before taking screenshot you should blur your secure information.
I read quite some articles about fragments, but I am still confused about how to do what.
I have a MainActivity, which displays two fragments side by side. In one of the fragments I have a button and defined in the fragments layout XML for the button
android:onClick="buttonClicked"
Now I want to implement that method
public void buttonClicked(View view)
I would have assumed that this has to be implemented in FragmentA.java and not in MainActivity.java. But it only works if that method is implemented in MainActivity.java. Why is that? To me that doesn't make sense. Pre Honeycomb a method belonging to one activity stayed in that activity, now on a tablet I am merging many activities to one MainActivity and all the different methods are merged? Whatever do you put for example in FragmentA.java then? What if you have to start you an own activity because this app runs on a handheld, then the onClick method has not to be in the MainActivity but in the Activity which needs to be called then. I am pretty confused at the moment...
I'm not sure what the specific problem is, but maybe this will help.
From the Android documentation on Fragments:
You should design each fragment as a modular and reusable activity component. That is, because each fragment defines its own layout and its own behavior with its own lifecycle callbacks, you can include one fragment in multiple activities, so you should design for reuse and avoid directly manipulating one fragment from another fragment.
That is, you should never manipulate a fragment from another fragment; rather, this should be done through the underlying Activity. Read the "Creating event callbacks to the activity" section in this article for more information (it's important stuff!!).
On the other hand, if you want the button to perform an action within the Fragment itself (i.e. if you wanted a Button click to change the text of a TextView within the Fragment), you should implement this in the Fragment, not the Activity (this is because the resulting behavior is contained within the Fragment and has nothing to do with the parent Activity).
Leave a comment and I can clarify if my post is confusing... I only recently began to understand Fragment's myself :).
Well,
I guess it is related to hierarchy of android context structure.
Activity is host of all child views and hence you can say fragment is actually using its host's context.And that's why when you use onClick with fragment system always searches it in Host activity of fragment.
Check it on.
Android developer onClick attribute description
I haven't checked one thing but you could put a test.
By providing implementation in host activity rather than in fragment,but use onClick on layout file of fragment.It should call parent's method.
I have a little problem to detect when the application is finished. I need to do some actions onDestroy like save the parameters into the database and make a final connection to the server.
The problem is that if I put the code in onDestroy its is called when the orientation changes for example. Putting
android:configChanges="orientation|keyboardHidden"
in the manifest for that activity the landscape/portrait layouts don't swap. And adding
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
}
Changes the layouts but the buttons and labels do not get the onClickListeners and the text labels correctly. How can I solve that? Thanks
The problem is that your layout items aren't initialized again because you're initializing them in your onCreate() function, and then you're disrupting them with a new layout in onConfigurationChanged().
One option is to move the initialization to a new function that gets called from both onCreate() and onConfigurationChanged().
Another option is to use the android:onclick="" (and related) attributes in your layout.
The option I would choose is different though. I would allow Android to manage orientation (and to call onDestroy()) and in onDestroy() I would install an Alarm for, say, 10 seconds (which I imagine is plenty of time to have onCreate() called again). In onCreate() I would cancel the alarm. When the alarm fires, I would perform my save actions.
Declare buttons and labels as class variable.
setContentView recreates your view, so you must rebind your data. the best approach would be a function called both from onCreate() and onConfigurationChanged(), with layout creation and bindings.
If you don't want to anything to happen when orientation changes occur, than you should not re-setContentView(). Basically you are telling your app: "DO NOTHING WHEN ORIENTATION CHANGES". So, remove the setContentView inside the onConfigurationChanged() or test for which orientation currently is active and then load desired layout resources.
When orientation changes onDestroy() is called because the changes restart your entire activity.
Read more here:
http://developer.android.com/guide/practices/screens_support.html#qualifiers
http://developer.android.com/guide/topics/resources/providing-resources.html
Orientation testing:
Setting the background of an Activity
Could you do that stuff in overriden finish() of the activity?