I have an application which needs to run on handheld devices and on tablets/kiosks etc. as far as the design is concern it is easy to maintain but now I have two different logic which needs to different entry points on different device. Following is my requirements.
If it is phone, I want to show login/signup screen then after login/signup it will take to main screen
if it is not phone (I mean if it is tablet/kiosk) it will directly go to main screen.
How can I achieve this? I took some idea from this thread on SO. but it is too old. Is there any reliable advance way to do that what I need.
Please do not mark as copy and do not close it because I am asking for new way to do it. so that the newbies can get it easily on one thread.
there is no such option for different launchers on different devices, but you can always check what you need in one (and only?) laucher (onCreate method) and start immediately "main" Activity if needed with finishing current "login"
edit:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(checkIfTablet()) {
startActivity(new Intent(this, MainActivity.class));
finish;
return;
}
// rest of code
}
Related
The app I'm currently building has the requirement that the app has to prevent the OS to take a screenshot of the app when it's being pushed into the background for security reasons. This way it won't be able to see the last active screen when switching between apps.
I'm planning to put this functionality in the application class's onPause method, but first I need to find out how I can achieve this functionality.
So is there anybody out there, that has a clue how to fix this?
Try FLAG_SECURE:
public class FlagSecureTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.main);
}
}
This definitely secures against manual screenshots and automatic screenshots from the ICS recent-tasks history. It also secures against screen recording (e.g., apps using the media projection APIs).
UPDATE: it also secures against Now On Tap or other assistants on Android 6.0; they will not get access to the details of widgets and containers in your UI if the user brings up the assistant.
UPDATE #2: however, not everything in the activity will be protected. Any pop-up windows — Dialog, Spinner, AutoCompleteTextView, action bar overflow, etc. — will be insecure. You can fix the Dialog problem by calling getWindow() on it and setting FLAG_SECURE. The rest... gets tricky. See this blog post for more.
Be careful about using WindowManager.LayoutParams.FLAG_SECURE, on some devices (verified on Samsung Galaxy ACE, e.g. GT-S5830) this will make the view scrambled. Looks like a Samsung specific bug. I recommend the following:
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
This is what a scrambled screen looks like:
This is working properly on ICS Samsung phones though, so I'm assuming problem is isolated to Gingerbread devices (or older).
The solution provided by CommonsWare continues to be valid also in Lollipop.
Just a note, if you want to continue to not see snapshots in recent list for the entire app, ALL the implemented activities should specify in the onCreate() method the flag getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
before setContentView();
Otherwise a snapshot in the recent list will show the first activity without the flag if the user navigated through it.
In case if someone is looking for a solution in which the app must secure (screen overlay) when the app is background or stick of all running app and the in-app app should allow screenshot.
Try Below:-
#Override
protected void onResume() {
super.onResume();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
#Override
protected void onPause() {
super.onPause();
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
Here is a solution for hiding content of an app by covering it with a splash screen when the app is put into the background. This is not using the FLAG_SECURE technique, I simply override the onPause and onResume methods of the screens and modify the view to show one that covers everything in the back.
https://stackoverflow.com/a/52976001/6686912
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
this worked for me, it prevents from taking screenshot and also any inbuilt or third party recording application from recording screen.
This is work for me after adding these line into the onCreate before setContentView of every activity.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_notification);
As of Android 13, there is a new way to prevent a screenshot being taken for the recent apps list, while still allowing the user to take screenshots while using the app: https://developer.android.com/reference/android/app/Activity#setRecentsScreenshotEnabled(boolean)
I am currently developing a game with the android development enviornment. And for the past couple of months I've been dealing with a nasty OOM error. My first problem was that I was placing my drawables in the wrong folder (Drawable-xhdpi in drawable folder). But now, the OOM error eventually happens as you go through the game.
It is a rpg, basically compoed of menus in activity layouts with animations and things. and I've tried everything I could to fix it. I've tried the unbindDrawables method:
unbindDrawables(View view) {
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
which does help a lot, but it does not fix the issue. And I cannot use any of the bitmap.factory options or anything, since I load my images through xml in my drawables folder. My images aren't that big by the way, as activities have a background of 720x1280, with some smaller images, and the most total images I'll have on screen at a time is around 8.
So this lead me to think that I may have a memory leak. I did ALOT of research, and I found out that use this(the activity context) will cause a leak, and I should use the application context. However, If I make the switch, there is almost no difference.
So I used MAT to figure out what was going on, and most of my memory is going to byte[], android.graphics.bitmap. And if I drill down to find the cause of this, it seems that java.ref.finalizer is causing all of the retained memory in the VM.
The only reason I could think this is happening, is because whenever I start a new activity I use,
Intent fight = new Intent(this, StartScreen.class);
//add this flag to remove all previous activities
fight.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(fight);
finish();
which opens a new activity, but closes the one we were just in. So, I'm guessing the bitmaps are not being recycled correctly whenever I finish an activity? or is closing and starting activities like this bad for memory?
I've been on Google all day trying to find the solution to this problem and I can't find it. Any soulutions are appreciated, thank you for reading this!
P.S if you would like to see any snippets of my logcat or code or anything, I am more than happy to post it.
P.S P.S My game has about 10-12 different activities I switch between. For example If I have activities A,B,C I open A, Open B close A, Open C close B, open B close C, open A close B.
EDIT: As request about my activities. Usually it is a menu, and when you press a button, that activity finishes, and then moves into another activity. Or buttons will do some math for things like selling, or doing damage to an enemy. One thing about my activity architecture, is that since I am closing every activity as I go to a new one, when I go back to the ones I closed, I am re-creating them. So I don't know if the old activities I finished still have memory in the VM that over time causes the Out Of Memory error, since it all builds up and keeps expanding. I explained My call for a new activity above. And the intent flag closes all past activities (if there are any) in the stack.
EDIT EDIT: As per request my oncreate and onDestroy:
OnCreate:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_screen);
//setting fonts
//a function that binds views by findview by Id and then sets their typeface
setFont();
//set up the music service
//connects the app to the background music service
playMusic();
//aquire wakelock
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
OnDestroy:
#Override
public void onDestroy()
{
super.onDestroy();
//unbinds the service
unbindService(musicConnection);
//unbind drawables (function above)
unbindDrawables((LinearLayout) findViewById(R.id.container));
}
you should destroy the activities that you don't need anymore it takes place in the memory. or if you dont want your user/player to go back to the recent activity you should finish the activity. and if you will notice. if you dont finish the activity and press the back button several times it is layered.
second you mentioned that it is a game. in android programming you need to consider your bitmap resources so to avoid getting an OOM error in your game make use of sprite sheet it will save a lot of memory and usage of bitmaps in your application. i encountered those kind of situation and bitmaps mainly causes the OOM error.
I will say it depends. but with your problem your answer is right here
Quick quote from the site
Note: In most cases, you should not explicitly finish an activity using these methods.
As discussed in the following section about the activity lifecycle,the Android
system manages the life of an activity for you, so you do not need to finish your own
activities. Calling these methods could adversely affect the expected user experience
and should only be used when you absolutely do not want the user to return to this
instance of the activity.
Read for more info
well i get you lucidly now, but im thinking of what you are tryna do here, so y dont you use FragmentActivity for B and C.. So, Activity A opens B..B is opened as fragment but works like activity-(thats fragmentActivity), and opens C which is most likely a Fragment..which i think would be perfect for your situation..
for more info about FragmentActivity click Here
no more activities back and forth.. and its gonna work like an activity..
I want to execute a piece of code (say, for example, display a Toast) every time that the app is opened. So far I have managed to do this every time the app is launched by putting the code into my MyApp.java file that extends Application.
However, if I press the homescreen or back out of the app and then go into it, the message doesn't reappear. It only does when I relaunch the app. Any idea how to do this?
EDIT:
basically im asking how to execute code everytime the whole APP is brought to foreground (this can be first time open, after another app was used, after user backed out of app, etc). Where would I place onResume code? It wouldn't be in a particular activity, would it, since I want it to apply when entire app appears in foreground, not just particular activity.
You can try writing that code in your activity's #Override-d onResume() method.
The only way to do this is,
Determine which app is currently in the foreground
.Follow this discussion for getting an idea for the best way to do it.
[Determining the current foreground application from a background task or service
Suppose, if the function name is 'getCurrentForgroundApp()',
You need a service to execute getCurrentForgroundApp(); every one second
(1-second interval is depending on your purpose, can be lower or higher).
Now, you can identify which app is running foreground in every second.
So, check if your app is the one running foreground. If true, then execute the toast or code you need.
This is how app-locker apps showing lock screen over selected apps, whenever they come to the foreground.
You have to use the onResume callback:
Android API
Example of use from previous SO question
In activity class:
#Override
protected void onResume() {
super.onResume();
//your code here
}
Over the past months I have been developing a versatile real-time game engine, and I have learned a lot, but I still feel very naive when it comes to the application life cycle. Specifically, I am trying to implement an Activity which can be shuffled in to the background by the user, then properly resumed.
My current architecture is as such: I have a an XML menu launcher activity which can create a real-time Game activity using intent. Relevant data in this Game activity is referenced through static data structures and variables. The Game activity creates worker threads in the onSurfaceCreate() callback of my SurfaceView object.
When a user presses the back button, the activity is destroyed, and they are sent back to the XML menu in the launcher activity. Fine, good for now. When the user presses the home button, the Activity is sent to the background. OK, great. My problems arise when the user tries to find their way back in the Game activity once is has been sent to the background. When the user touches the launcher icon, the Game is destroyed and the menu is re-launched. Also, when the user resumes the game through the task manager, the onSurfaceCreate() callback fires and the worker threads are started, but the game is frozen.
So, I have two questions. First, how do I resume my activity through the launcher icon, instead of re-launching the game? Second, when I resume my activity, what actions are necessary to restart my worker threads while persisting the game data?
Thanks!
EDIT: By request, I am including some code below. My onSurfaceCreate is a little bit complicated, it sends a message to another thread, which then implements the callback. I have verified that this implementation function fires when the Game activity is resumed.
protected void surfaceCreate()
{
Log.e(TAG, "surfaceCreate");
Thread gameThread = createGameThread();
gameThread.start();
}
protected final void onResume()
{
super.onResume();
resume();
}
protected final void onPause()
{
super.onPause();
pause();
}
These cryptic pause() and resume() methods simply set a boolean variable which prevents some game logic from being executed, they do nothing to hinder the worker threads, which should continue looping.
EDIT: Thanks Mohammad, for solving my first (although smaller) problem. It turns out that the launcher icon behaves differently when not connected by USB to the IDE. The second problem remains unresolved.
EDIT: All working! The second problem turned out to be an issue unique to my code, I apologize for that. I hope that this question can still be useful for those dealing with the launcher and IDEs.
There are multiple possible problems/solutions listed in this post. This includes misunderstanding of activity lifecycle and launchMode settings.
First, how do I resume my activity through the launcher icon, instead
of re-launching the game?
You are most likely missing definition for your onResume() and onPause() methods. Examples are here:
http://developer.android.com/training/basics/activity-lifecycle/pausing.html
Straight from the API:
onPause() Called as part of the activity lifecycle when an
activity is going into the background, but has not (yet) been killed.
onResume() Called after onRestoreInstanceState(Bundle),
onRestart(), or onPause(), for your activity to start interacting with
the user.
Check the Android Activity Lifecycle out:
http://developer.android.com/reference/android/app/Activity.html
One theory on your issue may be is that you're most likely going to onStop() (by hitting the home button) and the Android OS is looking for your onRestart(), but can't find it hence freezing/restarting.
Second, when I resume my activity, what actions are necessary to
restart my worker threads while persisting the game data?
Careful how you use the word restart. You want to pause and resume the application (not restart). Save data in onPause() (use a database or any other save feature you'd like). Load data in onResume(). Although, the activity should resume as normal if you just fill up these methods.
Now, if you want to save state for when you restart the application, you should save states in onStop() and/or onDestroy(). You should load states in onStart(). In order to save states, you can check this out:
https://stackoverflow.com/a/151940/2498729
For those using Eclipse (or any other IDE to run/test your application):
From what have you described you probably have overridden
android:launchMode in AndroidManifest.xml or if you are testing by
"run as" from Eclipse try exiting the application after installing and
auto-starting. Then start again from the emulator and test the Home
button behavior. I suppose this is because Android does not put
Activities on the OS stack when started from Eclipse and then the Home
button behavior is not as usual. If this does not solve your problem,
try reading
http://developer.android.com/guide/topics/fundamentals.html#lmodes.
I had launchMode set in my StartupActivity. THen I removed that (it
was set to "singleTask", it behaves like I want it; the app is
"resumed" to the Activity I expect, ie not StartupActivity but
MainActivity.
Source:
https://stackoverflow.com/a/1619461/2498729
http://developer.android.com/guide/topics/manifest/activity-element.html
According to this:
https://stackoverflow.com/a/3002890/2498729
You should change your andoird:launchMode to "Standard" (or "default").
Standard: A > B > HOME > B (what you want)
SingleTask: A > B > HOME > A (what you don't want)
I am executing maswebview class and I would like to finish only this activity. I tried maswebview.this.finish() but when executed, app is been closed. Then if I set a new view for the tab content, it is loaded properly and webviewmas dissapears but just for a while, then appears again fitting fullscreen. How to finish maswebview completely? ThanK you
public void onClick(View arg0)
{
/*
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
startActivityForResult(intent, 1);
Intent intentmas = new Intent (maswebview.this, mas.class);
intentmas.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intentmas.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intentmas.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentmas.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
View vista = getLocalActivityManager().startActivity("maswb", intentmas).getDecorView();
setContentView(vista); */
maswebview.this.finish();
Do you have any other activities of your app in the stack by the time you call finish()? If you don't, you'll want to start the desired activity instead of finishing the current one.
But actually it seems to me that you're trying to accomplish something that can be done simpler. Can you provide more info on the task at hand and your app structure you're trying to go about it with?
From what you said, it seems like you have tabbed UI and you're trying to show a webview in one of the tabs, then hide it.
First, I don't see why you want the webview in a separate activity. Seems to me you could just have it in layout of one of the tabs and just call setVisibility(GONE) to hide it.
Second - and this is important - looks like you're trying to implement tabs the old way - TabWidget, TabHost, etc. Since Honeycomb has been released, there's much more convenient way to implement tabbed UI - Action Bar Tabs and Fragments - that approach is much more convenient and will render your webview problems obsolete: there's a thing called WebViewFragment which is basically a WebView but smarter - it will handle its own lifecycle with minimum effort required from you (i.e. pause when removed, resume when added). It will take some effort to study up on Fragments, but it's well worth it. You can get Fragments API for pre-Honeycomb android sdks as a static library - it's called android-support-v4 and you can download it in Android SDK Manager.
Are you calling "maswebview.this.finish();" before the new Activity is started?
Also if you want to just start this new activity without having the old activity in existence then you can add android:nohistory="true" to your manifest.xml. This will cause the current activity to be the only activity in the queue.
See HERE
You need to provide a little more information for us to better understand what exactly is going on.
I hope this helps.
Try following code
#Override
public void onBackPressed() {
if(childView != null && parentLayout.getChildCount()==2){
childView.stopLoading();
parentLayout.removeViewAt(parentLayout.getChildCount()-1);
if(webView.getVisibility() == View.GONE)
webView.setVisibility(View.VISIBLE);
}else{
super.onBackPressed();
}
Do you have a parent activity which is launching this one? If yes make sure you don't call finish() after launching maswebview, that way the parent activity will remain in the stack. Once maswebview would exit, onResume would be called for your parent activity.