I have an APK that runs completely fine across several android levels varying from android 5 through 9. We started testing a new android 9 phone (Hot Pepper HPP-L55B aka Serrano), and I'm seeing an interesting issue that I'm hoping someone has come across.
All of my Activities extend a base activity that does some standard logging (such as logging onCreate, onResume, etc).
On app launch:
Activity 1 - MainLaunch
onCreate starts the activity Splash then calls finish
Activity 2 - Splash
onCreate sets the content view and finds the WebView on the screen.
onResume sets a gif in the webview so it's rendered on the splash screen. It also starts a thread that sleeps for a few seconds that then kicks off Activity 3. The gif animates as expected.
Activity 3 - Launchpad
onCreate sets the content view and finds references to other items on the screen (buttons and textviews).
onResume checks a few internal things, and may or may not hide things on the UI based on configuration. Nothing to exciting.
There are times this process will go through without a hitch, and other times where the UI that was being displayed in Activity 2 (splash) stays up while my logs are showing that the code thinks it's showing UI 3. The gif in this case is no longer animating.
As you click around on the splash screen the buttons that are referenced and would be showing on Activity 3 are being pressed. So basically like the splash screen is covering the 3rd activities screen and allowing button push pass through. If i turn the screen off/on again the splash screen still shows up. Throwing breakpoints in activity 3 get hit as the hidden buttons get clicked.
Anyone ever see this before or have suggestions how to fix it? This phone model seems to be the only one with the issue. So it definitely seems like a phone model problem and not anything i can control. Any suggestions?
This problem boiled down to the processor (MediaTek) being used in combination with the theme being used for the application. At least that was the only thing that was found different across the supported phones we tested.
The theme for the activities were changed:
from #android:style/Theme.Translucent.NoTitleBar
to #android:style/Theme.Light.NoTitleBar
Related
I am tasked with building an app that does not have a fixed screen order.
When started the app will contact a server an get a list of actions to perform.
So one launch could be
screen 1 - screen 5 - screen 7
next time
screen 3 - screen 5 - screen 9
I tested a simple app that does that; my Main activity starts the needed activity and that activity returns to the main activity, which starts the next needed activity.
In other words, all activities return to the Main activity which then determines which activity to start next.
It seems to work fine, but I have read that Activities should only be used for UI, my Main activity had no UI, it just controlled which activity happened next. So should I be using a different approach?
I am brand new to Android, but have decades of Java experience.
In case it makes a difference, I am using AS 3.0.1
Thanks
I'd suggest one activity and implementing your "screens" as fragments. This makes it really easy to code your logic for what screen comes next. You are just adding / replacing fragments and not starting and tracking result codes of activities. The business logic for each screen can still be fully encapsulated in the fragment.
A very odd issue that I'm not able to diagnose or figure out, so I'm hoping that someone else has seen this and might have a clue as to what's going on.
All Activities inherit from AppCompatActivity.
The scenario is as this:
Activity 1 (extends AppCompatActivity) starts Activity 2
Activity 2 performs some action after user input and then exits via onBackPressed
Activity 1 displays a Snackbar based on the action performed with Activity 2 as a means of confirmation
The problem is that the Snackbar doesn't show at all or is delayed and flickers on as it is dismissing. If I touch the screen and interact with Activity 1, the Snackbar becomes immediately visible.
I also turned on "Show layout boundaries" via the Developer Options and I can see that the Snackbar isn't actually being displayed (invisible) until I touch the screen (or until it starts to animate out).
I created a sample application and it seems to be working fine there, but no such luck in our production application. Activity 1 itself is displaying a lot of information and content in a ScrollView, but I wouldn't think that this would cause an issue, unless there are rendering passes that are happening that I can't tell and that is causing the delay in display.
I've created a project that you can use to demonstrate this problem. I believe that this is a bug, and you can work around it by not using your own transitions. Though I also believe that not all transition animations will cause the issue. I think the hold animation in this case is the culprit.
Here is a brief outline of the issue:
Activity 1 and 2 both have Scroll Views with a bunch of content.
Activity 2 opens Activity 2 using overridePendingTransition( slide_up, slide_down), though this isn't necessary for this example.
Activity 3 displays content and then is closed:
a) using overridePendingTransition( hold, slide_down ). In order to see the Snackbar in this scenario, you will need to touch the screen and interact with Activity 1.
b) using no Transition. The Snackbar should be visible.
My solution to this issue was to remove overridePendingTransition. Please comment if you have additional ideas about this.
I am using the Android MediaRouter (API 16) and Presentation (API 17) classes to generate & manage a secondary display. I followed the example in ApiDemos to create unique non-mirrored output, and so far it works fine (testing with Nexus 10 connected to HDTV via HDMI cable).
Now, I have a situation where I want the Presentation object created in Activity X to continue running on the secondary display, even if Activity X invokes another Activity Y. In this situation, Activity X is still on the stack, but Activity Y is now on top of it.
The problem is that when Activity Y starts, the physical secondary display reverts to mirroring. When I exit Activity Y, the content of Activity X's Presentation goes back (since I never called dismiss() on it).
So the question is: How can I keep a Presentation attached to a secondary display running on that display, even if a subordinate Activity is running on the local device?
UPDATE: One way I thought of doing this is to instantiate the Presentation object from a background thread; then the subsequent creation of another Activity should not interfere with the content being written by the background thread to its Presentation object. But I'm not sure this will work, as it's generally not allowed to update a UI from a background thread.
Another approach would be to disable the use of secondary displays by the subordinate Activity, if possible, thereby preventing it from reverting the secondary display to mirroring when the new Activity becomes active. But I haven't found a way to do this either. Thanks again for any suggestions.
I implemented one of the approaches suggested by #CommonsWare (and independently by Mark Allison in answer to my question on his blog). Thanks for your suggestions!
In review, THE PROBLEM was I couldn't keep a second screen presentation running in the background across Activity invocations on a local device. This was because the Presentation class is implemented as a subclass of Dialog, and is therefore tied to an Activity instance. So when a new Activity started up, the second screen went back to mirroring (instead of displaying other content I was specifically generating for it).
THE SOLUTION was to refactor all "subordinate" Activities into Fragments of the original Activity (i.e., the one that launched the second screen). Then, instead of calling startActivity(), I start/stop the new Fragments using FragmentTransactions. The net effect is that the Activity that started the Presentation is still running, so the secondary display is no longer interrupted when a new Activity starts.
My case was further complicated by the fact that the top level Activity (which starts the second screen) was actually a SherlockFragmentActivity that uses a ViewPager and FragmentStatePagerAdapter -- so I had to cram all this into a Fragment. It also required explicit management of ActionBar tabs, menu items, and home icon.
Overall, I think the code is a little less transparent ... but it works!
NOTE: It's good that Google has implemented a secondary screen interface. But I'm not sure why they did it the way they did. Rather than shoe-horning the Presentation class into Dialog, it would have been nice if they provided a more general solution that could easily run in the background, i.e., regardless of foreground Activities on the device. A solution like this would have saved me from a lot of code refactoring, as described above.
Bringing this question back from the dead willing to help someone with the same problem somewhere in time,
I've recently came into a far deeper, but similar, problem: I had to display a presentation anywhere on the system (I work with embedded android) and in the main screen any app could be used.
I first thought of creating a Service that managed the display of the presentation and was initialized at the startup of the application. But the problem was that I couldn't show the presentation because, as you mention, it inherits from a Dialog and the same problem that happens when you call getApplicationContext() when building a dialog, occurred.
My solution was:
There is a WindowManager.LayoutParam called TYPE_SYSTEM_ALERT that is used to display alerts like the Low Battery alert Dialog. Using this property you can create a Dialog from a service and display it properly and as the Presentation class is a children of the Dialog, simply setting this property made it work.
The magic happens here:
WindowManager.LayoutParams l = mPresentation.getWindow()
.getAttributes();
l.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
mPresentation.show();
Just reminding that in order to achieve that your, application XML should have the SYSTEM_ALERT_WINDOW permission.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
I think that this should solve your issue as well, but it is a little bit delicated and you need a proper treatment to stop the presentation as soon as you needed.
The main activity of my app is defined in the Android manifest file with the following attribute:
android:theme="#style/Theme.Translucent.NoTitleBar"
This makes the activity transparent, which in turn makes it possible to control the transparency of my app in code by manipulating the main View object (e.g., by invoking setVisibility(View.INVISIBLE) on the main view). This works fine.
However, one undesirable consequence of this approach is that when the app is launched there is no visible response until my main View is displayed. Normally, the default black background of an app's main activity is immediately visible when an app is launched, which provides immediate confirmation that the app is starting to run in response to the user tapping its icon in the launcher. But with a transparent background, the user continues to look through the background at the display from which the app is being launched until the main view is displayed, and so it appears (during that interval) as if nothing has occurred.
Even on a device with mediocre performance (e.g., the Motorola Droid) my view comes up in about one second, which is not too bad. However, on a really slow device (e.g., the G1) it can take almost four seconds. While this is not a disaster, I'd prefer an immediate response so that the user is not left wondering whether the app was in fact triggered.
I have tried removing the transparent theme, which results in immediate confirmation via a black background, as usual. However, I've been unable to set the activity background to transparent in code once the app has been initialized.
I've invoked setTheme() on the activity just prior to calling setContentView() for the first time, passing it a transparent theme, but this does not make the activity transparent.
I've also tried this in onCreate() (again, just prior to calling setContentView()):
ColorDrawable transparentDrawable = new ColorDrawable(Color.TRANSPARENT);
getWindow().setBackgroundDrawable(transparentDrawable);
This also appears to have no effect.
I've also tried using a theme in my manifest that has android:windowBackground set to a drawable that is a mostly transparent PNG, but with some text (e.g., the app's name) superimposed on the transparent background that would provide a cue to the user that the app was loading. Unfortunately, the moment I use a drawable as part of the theme, the background fails to display at all until after the main view is initialized.
All time-consuming initializations are already being done in a worker thread, so I'm not looking for advice on how to accomplish that. The view itself just takes a certain amount of time to display, and while it is fairly quick, nothing beats the instantaneous response of seeing the main activity's background as soon as the app is launched.
Even on a device with mediocre performance (e.g., the Motorola Droid) my view comes up in about one second, which is not too bad. However, on a really slow device (e.g., the G1) it can take almost four seconds.
It should come up in milliseconds. Make sure you are not doing excessive work on the main application thread.
The view itself just takes a certain amount of time to display, and while it is fairly quick, nothing beats the instantaneous response of seeing the main activity's background as soon as the app is launched.
Then initially display something else that is cheaper to bring up (e.g., ProgressBar), replacing it with your regular UI when it is ready.
I've upvoted CommonsWare's answer, because he pointed me in the right direction, which is away from trying to change the transparency of the main activity after it is launched (something I'm beginning to suspect cannot be easily done).
However, that advice cannot itself be the accepted answer, given that it is only a pointer in the right direction.
The answer I decided upon, given this guidance, was to create a splash display. However, I could not find a truly good android splash example anywhere. So, I devised one, and it is working very well for me, and completely solves my problem.
Because creating a splash display is a more general question than the one I started out with, I have placed my detailed description of how that can be done as an answer to a question about how to implement a splash screen, and have linked to that answer below:
Create a true splash screen
When a webview is done loading it only shows a white page. The strangest part is that events (like a click on an anchor) are still working. After i perform this event and go back (with the back key), the webview is rendered correctly.
This behavior doesn't appear on a HTC Desire with Android 2.3.7, but it appears on the Asus Transformer Prime with Android 4.0.3.
If i put a Thread.sleep(10000) in onPageFinished() the page is visible for 10 seconds but then turns white, events are still working.
The Activity is the Launcher activity and extends a custom base activity. Every activity in my app extends this base activity. The base activity detects if a user is authorized and shows the login activity is needed. When i press the back button after the login activity is displayed, the launcher activity is shows the behavior as described above.
Don't know what to do right now to solve this problem...
The easiest way is to say that it is a bug in Android. But that doesn't solve my problem. Any suggestions to solve this case?
I have had the same problem for a couple of hours, what solved the problem for me was removing the setting below from my WebView constructor call:
this.setLongClickable(true);
I do not know why this worked.