I am working on app which will serve as Home Screen Lock. The app will support only 4.1 and above versions. The issue is handling the Home Button. I understand that we cannot override/disable Home Button, so it has to be handled a different way. I have been struggling for almost 2 weeks and tried many umpteenth ways but none of them working as expected. Main Activity is the one which will be on top and user need to enter his set password here to unlock the device. I have set my MainActivity as Home so the user is prompted to select between default launcher and my app. So expected action is to select my app as Launcher 'always'. Also I have set an flag in broadcast receiver whenever MainAcitivity is started. This flag is used in MainActivity to launch system Launcher in case MainActivity isn't started by broadcast receiver.
Everything is working fine till this point and approach. Issue is when I click on my app to change password or access other features, it doesn't open the app and opens the system launcher. The reason is it checks the flag in Main Activity and since it is not started by broadcast receiver, it doesn't launch MainActivity now and starts the system launcher. Below are code snippets:
Manifest File:
<activity
android:name=".MainActivity"
android:excludeFromRecents="true"
android:label="#string/app_name"
android:launchMode="singleTop"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</activity>
My Broadcast Receiver
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF) || action.equals(Intent.ACTION_USER_PRESENT)) {
AppSession.getInstance().setReceiverCall(true);
MainActivity.isStarted = true;
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
context.startActivity(i);
}
Main Activity where I check the flag and start the system launcher. I amy doing this on onResume
if (!MainActivity.isStarted) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(mPackageName, mName));
startActivity(intent);
}
mPackageName & mName are system launcher name.
I tried other approaches as well but only one of the thing is resolved. Either home button is handled correctly and then my app isn't launched. If app is launched then on Home button press from anywhere it always brings my MainActivity on top.
I know this is doable as its done in many ScreenLock apps but somehow I am missing something. Please advise.
Related
My app (a game) has two activities: a launcher activity which shows logo, does initializations and is the main activity of my app, and a client activity which does the 3D rendering and is started by the launcher activity. Thus when the app is running, the back stack is: launcher | client.
What I want with a link is:
if the app has not been started, clicking the link should first start the launcher activity, then the launcher activity start the client activity. Finally the game runs in the client activity.
if the app is running (running in the client activity), clicking the link should switch to and notify the app that the link is clicked (either in launcher or client is ok, better in client), instead of starting another launcher activity.
What I have tried:
I added an intent filter in the declaration of the launcher acitivity:
<activity android:name=".Launcher" android:label="TestApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="myapp" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity android:name=".Client" android:label="TestApp">
</activity>
And the intent filter works when I click the link: myapp://, the launcher activity is started. But the problem is the launcher activity is started in the browser's task. If I already have an app running, there will be a new instance of my app started in the browers back stack, instead of switching to the already running app.
Then I tried add the attribute android:launchMode="singleTask" into the activity declaration. Then clicking the link will start a new task and the Launcher activity is started in that task. And if the app has already running, the running task is switched to foreground, that's what I expect. But the problem is, the back stack of the app task is changed from "launcher | client" to "launcher", the client activity is gone.
I hope that there is only one instance of my app. Cliking a link should start the app if the app is not running, otherwise switch to the app without affecting the app's current running states.
I searched a lot but don't find a solution, please help me, thanks.
Click here for app links assistant
I'm trying to open my application from NFC app chooser dialog which appears when NFC tag is detected by the system. My app appears in chooser dialog.
Case 1:
When application is running in background.
On NFC tag detection bring background activity(top activity in task) to foreground.
Problem
I need to specify which activity handles the nfc intent from system in manifest file. So when user selects my application from app chooser system launchs that specified activity. Instead of bring background activity to the front.
Case 2:
When application is not running lunch application with it's launcher activity.
Problem
To achieve this I need to specify launcher screen as NFC intent handler in manifest file. By doing this my app will fail in case 1!
AndoridManifest.xml snippet
<activity android:name=".activityName" ...>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:category="android.intent.category.DEFAULT"
android:resource="#xml/nfc_tech_filter" />
</activity>
What can be the solution to satisfy both cases?
I tried with ActivityManager but didn't get the solution with it.
I solved my problem by adding following code into launcher activity's onCreate(). I kept intent filter and meta data same for launcher activity. The trick here is to check if application task is already running into system or not.
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
finish();
return;
}
Above code will check if application task is already running or not. If its running then launcher activity will close him self and will brought top most activity of task to the front.
Reference:
https://stackoverflow.com/a/21022876/2465752
https://developer.android.com/reference/android/R.styleable.html#AndroidManifestActivity_launchMode
I am using TAG_DISCOVERED action in my TagActivity and if my application is already open, I want to close it before my TagActivity is opened. However, When my TagActivity is opened with NFC, I added some logic so it navigates to main activity when pressed to back button, however the already opened app is still there and when I close the navigated main app, it agains show me my previously opened app. How can I close the app if I open my TagActivity with nfc?
<activity
android:name=".activities.TagActivity"
android:screenOrientation="portrait" >
<!--Registering app for receiving NFC's TAG_DISCOVERED intent-->
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
Edit: I thought the flag solved my problem but apparently I didn't test it properly. The real solution to my problem is to add android:launchMode="singleTask" to my activity in manifest file.
I added FLAG_ACTIVITY_NEW_TASK flag to my Intent when returning back and that solved my problem.
startActivity(new Intent(this, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK))
I have created a Home Screen replacement app. As per some of the suggestions here on SO, I approached this by creating the following two activities:
<activity
android:name=".Activities.GhostLauncherActivity"
android:enabled="false"
android:label="#string/title_activity_ghost_launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:name=".Activities.HomeScreenActivity"
android:enabled="true"
android:label="#string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
Then toggling their enabled state as follows:
ComponentName component = new ComponentName(this, GhostLauncherActivity.class);
ComponentName secComponent = new ComponentName(this, HomeScreenActivity.class);
packageManager.setComponentEnabledSetting(component, packageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
packageManager.setComponentEnabledSetting(secComponent, packageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
packageManager.setComponentEnabledSetting(component, packageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
This works like a charm. Every time I run the Java code above, the user is prompted to select a Home Screen app, with mine listed as one of the options. The HomeScreenActivity is itself a launcher screen: there is some GridView of apps that can be launched.
As per my question: when an app is launched from the Home Screen, pressing Home will return you to HomeScreenActivity. Perfect.
However, you can also access the SettingsActivity from within the Home Screen. Simple enough, the following code exists somewhere:
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
Now when I press the Home Button, the first time everything works fine...but the second time I go to settings, the Home button does not work. My app remains on the Settings screen. Even setting aside the the fact that it worked the first time, what could cause the Home button to stop working in my Home Screen replacement app? I have selectively commented out chunks of code from both Home Screen and Settings, exhaustively to check if any particular code chunk was responsible: none seem to be the culprit.
This error seems to be happening at some higher level and I can not figure out what that is. I am running Android 5.0 on my device. Has anyone experienced anything similar and if so, how can I address this issue or where else should I search for fixes within the code?
I was having the exact same problem; trying to launch my own activity from my home screen app. I found that adding the following line to my HOME activity and the sub-activity in the manifest fixed it:
android:launchMode="singleInstance"
I'm developing an application where a registration screen is required,
I initially put the registration sreen as the default
<activity android:name=".RegistrationActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
And after successfully registered I should make the user never see this screen again
My work around was to make a new intent to the main actual screen
Intent i = new Intent(this, SettingsActivity.class);
startActivity(i);
but what it does is that when I press back I see the registration screen again
Thanks
Try this:
startActivity(new Intent(getApplicationContext(), MyNewActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK));
this.finish();
Set android:noHistory="true" in the activity entry for your registration activity in AndroidManifest.xml. That will prevent the activity from being saved on the stack and it wont show up when you press back button.
What you do is make your main page your "LAUNCHER" activity. Then you check if the user is registered. If the user is not registered send them to the Registration Activity. When your user is finished registering finish the activity and refresh the main page when you return.
It's a good idea to keep the history of pages the app has been to, until you learn how to manage the application stack.