Reuse a single GLSurfaceView nested inside multiple activities - java

I have a usecase to make a single GLSurfaceView context, then reuse it on different Activity pages in an Android application as of API 26. In other words, I have a single OpenGL scene with GL state saved inside the context, that must be useable from different 'pages' in the Android app. Creating new GLSurfaceViews is out of the question, because we cannot lose the state we've put into GL when we change pages.
Surely I'm not the only person who has need of this... how is it done? All examples assume you don't need to show the same scene on multiple activities, or that it's perfectly acceptable to waste a bunch of time/memory recreating the same GL state over and over.
I'm aware of the 'activity life cycle', which is why I've tried to entertain the notion of making a 'dedicated' GlSurfaceView activity, and then attempting to figure out how to 'nest' this dedicated activity in other activities, but I'm unsure if that method could achieve the correct end. Thoughts?
EDIT - I forgot to mention -- is this possible with 'fragments'?
https://developer.android.com/guide/components/fragments

Update -- As near as I can tell this is intentionally walled off by Android API. Their intention with GLSurfaceView appears to be that it is tied to one activity only, EVER. When that Activity is gone, your GL context is 100 percent always gone.
This is why most applications with GL needs do not ever move between activities, and resort to operating within a single Activity

Related

Android keep button or view in front of all activities within the app without using baseActivity

After a lot of time spent I can't find the solution. I want a button or any clickable view should stay visible for all activities and it should be only for one specific app not like chat heads. I am basically making a library so that's why I can't use base activity.I have attached the image as well for a better explanation. How can I achieve this any suggestions? thankyou...
I
It sounds like you need a ViewOverlay. This is the API documentation.
ViewOverlay is usually tied to a single view, but if you wrap it in a fragment, you should be able to attach it to each view in your application. This should create the effect of an of an application scoped overlay.
There may be a more elegant way of doing this, but I am not aware of it.
EDIT: You can also wrap your layouts inside a frame layout(s) along with a seperate nested view (the view that you want to keep on top of the stack).
Frame layout creates a 'stack' of inner views. If you use this approach, you can programmatically ensure that there are exactly two views present and visible as children of your frame layout at all times. one will be the layout tied to your current activity. The other will be the view that you want to be overlayed.
I know that the term 'programmatically ensure' is vague. This is because there are many ways to make this happen. It is up to you to decide which way best suits your needs.

Android: Customizing recent apps thumbnail (screenshot by default)

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.

Eclipse ADT automatically creates a fragment for Activities. Why?

I vaguely understand what fragments are used for. However, I don't understand why ADT seems to suggest that we should ALWAYS use them. I am aware that I can simply delete the fragment layout, as well as the code in Activity for the fragment. But is it ACTUALLY recommended to use fragments all the time? What are the benefits of not deleting it?
Is there even a point of an Activity having a single fragment? What is the difference with it having no fragments at all?
Additionally, how do you know whether to create multiple fragments in one Activity, multiple Activities with a single or zero fragments or a combination of Activities and fragments?
For example, if you have a Terms and Conditions button in your Activity, and you want it to open a screen containing a document listing the terms and conditions, should I be starting a new Activity for that? Or should I just move a fragment containing this content to the front?
Using Fragments is how modern apps are developed today.
Some of the benefits are a better performance when switching content (lets say 2 fragments)
because you are not leaving the current Activity.
Also, apps with swipe tabs (for example) are built with an Activity as a container and Fragments as the content itself.
Other benefit is that you can do much more with one activity, distributing work between the fragments. Each Fragment have its own Layout and therefore its own components, so maintaining the code and keeping organized is easier.
Eclipse does this way as suggesting a start point. You can totally ignore this and start from scratch. And that's all.
I suggest you to keep the Fragment to start getting used to it. Even if there is just one.
And, if later you need to work more with that Activity, it will be easier to add new features by creating a new Fragment, without modifying your previous code.
Good luck.

Android - 2 Activities active at the same time

I have a GameActivity. I also have a transparent ChatActivity running on top if the user presses the Chat options from the Menu (onOptionsItemSelected). The problem is, when a player starts the ChatActivity before I start the game, an odd behavior occurs and the game won't start.
Is there any way I can keep GameActivity active while ChatActivity is visible?
I fired up the ChatActivity using the normal way:
startActivity(new Intent(GameActivity.this, ChatActivity.class));
Thanks for your help.
You can't have two activities in one activity. However; one design you could possibly achieve is introduce a design that allows the user to swipe the screen to bring up the chat view and swipe in the opposite direction to hide the view.
Have the main Activity that is running maintain that view via an async process so that it can be updated as necessary and does NOT interrupt the user.
You could take a look at FLAG_NOT_TOUCH_MODAL (and maybe FLAG_NOT_TOUCHABLE), using 2 activities on top of each other, making the top one transparant and give it that flag/those flags (not sure if you can actually touch windows you create within that activity, didn't try that yet)
you could also take a look at this. It's not exactly the same thing, but maybe you could rework it a bit to fit your needs
I know this is very very late,but this answer could be of use of anyone new.
For achieving the kind of design mentioned here, you could implement fragments instead of having two activities.

When to use new layouts and when to use new activities?

I'm making a game in Android and I'm trying to add a set of menu screens. Each screen takes up the whole display and has various transitions available to other screens. As a rough summary, the menu screens are:
Start screen
Difficult select screen
Game screen.
Pause screen.
Game over screen.
And there are several different ways you can transition between screen:
1 -> 2
2 -> 3
3 -> 4 (pause game)
4 -> 1 (exit game)
4 -> 3 (resume game)
3 -> 5 (game ends)
Obviously, I need some stored state when moving between screens, such as the difficulty level select when starting a game and what the player's score is when the game over screen is shown.
Can anyone give me some advice for the easiest way to implement the above screens and transitions in Android? All the create/destroy/pause/resume methods make me nervous about writing brittle code if I'm not careful.
I'm not fond of using an Activity for each screen. It seems too heavy weight, having to pass data around using intents seems like a real pain and each screen isn't a useful module by itself. As the "back" button doesn't always go back to the previous screen either, my menu layout doesn't seem to fit the activity model well.
At the moment, I'm representing each screen as an XML layout file and
I have one activity. I set the different buttons on each layout to call setContentView to update the screen the main activity is showing (e.g. the pause button changes the layout to the pause screen). The activity holds onto all the state needed (e.g. the current difficulty level and the game high score), which makes it easy to share data between screens. This seems roughly similar to the LunarLander sample, except I'm using multiple screens.
Does what I have at the moment sound OK or am I not doing things the typical Android way? Is there a class I can use (e.g. something like ViewFlipper) that could make my life easier?
By the way, my game screen is implemented as a SurfaceView that stores the game state. I need the state in this view to persist between calls to setContentView (e.g. to resume from paused). Is the right idea to create the game view when the activity starts, keep a reference to it and then use this reference with setContentView whenever I want the game screen to appear?
This question has been asked a lot. Did you read these other posts?
Android: What is better - multiple activities or switching views manually?. This link in particular talks about the Android Design Guidelines which "don't mention switching Views at all; it's centered around an Activity-as-View design."
Android - Should I use multiple activities or multiple content views
Android app with multiple activities
How to pass the values from one activity to previous activity
I'm not sure what you mean by the back button not always going back to the right screen correctly. I've got a game with a similar structure to yours, and the back button always takes the user correctly up the chain of activities.
Furthermore, using the onResume, onPause etc is somewhat necessary. What happens to your application if the phone rings? (Yes I know, some people still do strange things like using their phone to receive calls! :P) The OS tries to call the onPause method in your activity, but if that isn't implemented then your application won't act as expected. Another useful thing with onResume is it lets you update your tables as soon as the user returns to the view. For example, your player has just completed a level and is then brought back to the select difficulty screen. If you simply recover the previous screen from memory, it might not have been updated to take into account that a the level was just completed. However, if you put some code in onResume to handle that, then that will always be executed before the player sees the screen.
Lastly, you say transferring data around activities is a pain with intents - yes, that's probably true. But I usually find transferring any kind of complex data a pain, no matter how you do it. Are intents really that much worse, or is it just that things aren't as easy as you'd hoped? I don't mean any offense with that; I also often find things which intuitively seem easy to be rather frustrating to implement in code.

Categories