I'm making a launcher application with another settings activity to tweak the launcher.
Now, i don't want the launcher to be displayed as elligible upon pressing the home button until the user has not set it up up first (they will be asked to do that once the app downloads via notifications) through the settings activity.
So, can i suppress my launcher activity from running until after first run of application, and if not, then how to know first run of an activity.
PS: I already know how to implement first run of application.
This is based on the "Settings Activity" project created using Android Studio's "Start a new Android Studio project" template. After the project is successfully created, add a new activity class (that would be your launcher activity in your current project); for this example, it is a plain empty activity.
public class HomeScreenActivity extends AppCompatActivity {
}
Then add AndroidManifest.xml entries for that activity:
<activity
android:name=".HomeScreenActivity"
android:enabled="false"
android:label="#string/app_name">
<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>
Pay attention to android:enabled="false", that is the important part here. That way your launcher activity will be disabled by default. You will change it's state after user goes through the setup process.
In this example, I simply added a SwitchPreference and changed HomeScreenActivity's state based on the user click.
private SwitchPreference prefEnableDisableHomeScreen;
private PackageManager packageManager;
private ComponentName homeScreenComponent;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
packageManager = getActivity().getPackageManager();
homeScreenComponent = new ComponentName(getActivity().getApplicationContext(),
HomeScreenActivity.class);
prefEnableDisableHomeScreen = (SwitchPreference) findPreference("enable_disable_home_screen");
prefEnableDisableHomeScreen.setChecked(getIsComponentEnabled(homeScreenComponent));
prefEnableDisableHomeScreen.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object o) {
boolean previousState = prefEnableDisableHomeScreen.isChecked();
setComponentEnabledSetting(homeScreenComponent, previousState
? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
: PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
prefEnableDisableHomeScreen.setChecked(getIsComponentEnabled(homeScreenComponent));
return false;
}
});
}
private boolean getIsComponentEnabled(ComponentName componentName) {
int state = packageManager.getComponentEnabledSetting(componentName);
return PackageManager.COMPONENT_ENABLED_STATE_ENABLED == state;
}
private void setComponentEnabledSetting(ComponentName componentName, int newState) {
packageManager.setComponentEnabledSetting(componentName, newState, PackageManager.DONT_KILL_APP);
}
Hope this helps.
Related
I have an app for which the requirements are to launch it on detection of a non-NDEF NFC tag, so I'm using the TECH_DISCOVERED filter on my main activity to do so:
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
This works fine, however some users complain that their phone case doubles as a holder for their credit cards / smart cards and hence the app is unintentionally launching when they close their phone case. These users don't want to have to disable the device NFC setting (and that can't be done programmatically) so my question is: is it possible to programmatically stop an app launching by NFC intent from within that app?
The best idea I can come up with is to have the NFC intent launch a non-UI Activity (one that doesn't call setContentView) and have this check if some persistent flag has been set (by a UI control in the main activity) and if the flag is set, do not launch the main activity.
Is there an easier/more elegant solution?
The app could simply try to check whether the "discovered" tag belongs to the app (i.e. the datastructure is as expected, resp. the TagType is as expected), and if not stop again. Whether you make that visible to the use or not is up to you ...
My solution to this was to launch a headless (invisible) activity via the NFC intent and use a shared preference (set by a UI switch via the main activity) to determine whether to launch the main activity.
AndroidManifest.xml:
<activity android:name="com.mypackage.NFCLaunchActivity" android:theme="#android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="#xml/nfc_tech_filter" />
</activity>
res/nfc_tech_filter.xml:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
</tech-list>
</resources>
MainActivity.java:
public static String SETTINGS_NAME = "settings";
public static String shouldLaunchByNFC = "launchWithNfc";
// Call on changing UI state
protected void setShouldLaunchByNFC(boolean enableLaunch) {
setSettingBoolean(this, shouldLaunchByNFC, enableLaunch);
}
// Call to set initial UI state
protected boolean getShouldLaunchByNFC() {
return getSettingBoolean(this, shouldLaunchByNFC, true);
}
public static void setSettingBoolean(Activity activity, String name, boolean value){
SharedPreferences settings = activity.getSharedPreferences(SETTINGS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(name, value);
editor.commit();
}
public static boolean getSettingBoolean(Activity activity, String name, boolean defaultValue){
SharedPreferences settings = activity.getSharedPreferences(SETTINGS_NAME, MODE_PRIVATE);
return settings.getBoolean(name, defaultValue);
}
NFCLaunchActivity.java:
import static com.mypackage.MainActivity.getSettingBoolean;
import static com.mypackage.MainActivity.shouldLaunchByNFC;
public class NFCLaunchActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView explicitly omitted
boolean launchWithNfc = getSettingBoolean(this, shouldLaunchByNFC, true);
if(launchWithNfc){
Context context = this.getApplicationContext();
Intent intent = new Intent();
intent.setClassName(context, context.getPackageName() + ".MainActivity");
context.startActivity(intent);
}
finish();
}
}
I have managed to implement the following method coding that allows the app to perform an auto-launch when the device is booted/started-up. However, when I tested out the implementation code, it failed to work, the app has failed to perform an auto-launch when the device is booted. Can anyone please help or advice me what could be the possibilities? Thank you.
Manifest.xml
<uses-permission
android:name="android.permission.RECEIVE_BOOT_COMPLETED">
</uses-permission>
<receiver android:enabled="true" android:exported="true"
android:name="com.dapoaugury.apps.robotapp.AutoStartUp"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
android:installLocation="internalOnly">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
AutoStartup.java
package com.dapoaugury.apps.robotapp;
/**
* To Auto-Start Application on Device Start-up/ Boot
* Created by dev02 on 10/7/15.
*/
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AutoStartUp extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)){
//To start new intent when phone starts up
Intent i = new Intent(context, MainActivity.class);
// To put activity on the top of the stack since activity is launched from context outside activity
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// EDITED
i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.startActivity(i);
}
//To Start Application on Phone Start-up - 10/7/2015(END OF VERSION)
}
}
MainActivity.java (Mechanism that is suppose to be manually launch when app is first installed)
public class MainActivity extends Activity {
public static long AppElapsedTime;
public static long AppElapseTime_hr;
public static long Process_startTime = System.nanoTime();
public static long CurrentProcTime;
private static Context context;
public final static int GREEN = 0;
public final static int BLUE = 1;
private static int cTheme = GREEN;
WebView webView;
ProgressBar pb;
#Override
public void onCreate(Bundle savedInstanceState) {
...........
}
A newly installed app is placed in a "stopped" state until the app is actually launched for the first time. In this state none of your components will be activated, so your BOOT_COMPLETED receiver will not run. You need to include an activity and have it be opened by the user; you can always disable the Activity using PackageManager later.
This behavior was introduced in Android 3.1, you can read about it in the release notes (under the heading "Launch controls on stopped applications").
I have option in my app to start browser and load imdb website.
I'm using ActionView for this.
Intent intent1 = new Intent(android.content.Intent.ACTION_VIEW,
Uri.parse(website));
try {
activity.startActivity(intent1);
} catch (Exception e) {
Toast.makeText(activity, R.string.no_imdb, Toast.LENGTH_SHORT)
.show();
}
The problem occurs when I tap on back button.
When default browser app is launched everything is ok.
When Opera Mini app is launched, when I tap on back button, it seems like my app receives two back actions, and finish my current activity.
How to prevent this?
Try starting the intent in a new task:
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Or
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Please add this code to your android manifest for activity that you need return
<activity
android:name="YourActivityName"
android:launchMode="singleTask">
<intent-filter>
<action android:name="schemas.your_package.YourActivityName" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.ALTERNATIVE" />
</intent-filter>
</activity>
and add this to your web page
click to load app
because only one app has this action name (schemas.your_package.YourActivityName) on your phone, web page directly return to app
Also You can Use Airbnb DeepLink lib
Example
Here's an example where we register SampleActivity to pull out an ID from a deep link like example://example.com/deepLink/123. We annotated with #DeepLink and specify there will be a parameter that we'll identify with id.
#DeepLink("example://example.com/deepLink/{id}")
public class SampleActivity extends Activity {
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent.getBooleanExtra(DeepLink.IS_DEEP_LINK, false)) {
Bundle parameters = intent.getExtras();
String idString = parameters.getString("id");
// Do something with idString
}
}
}
i'm just starting out with Android and i think i'm missing something.
It seems like in Android you decide at development time which activity will be the first to be displayed in your application.
i would like to write my application in such a way that some kind of a centralized controller starts executing and it decides which activity should be first
(for example, based on some data obtained from somewhere)
is that possible to do, and if so, how?
thanks.
Most folks do it by launching an activity that just picks up the config it needs and then starts up the "real" activity. One hiccup is that the activity first launched will be on the task stack, but if you set android:noHistory="true" for the initial activity the process should be invisible to the user.
The below method can be used for showing tutorial screens on first app launch.
AndroidManifest.xml:
<activity android:name=".activities.LaunchActivity"
android:noHistory="true"
android:theme="#android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".onboarding.OnboardingActivity"/>
<activity android:name=".activities.MainActivity"/>
LaunchActivity.java:
public class LaunchActivity extends Activity {
public static final String FIRST_APP_LAUNCH = "com.your.package.name";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (isFirstAppLaunch()) {
setFirstAppLaunch(false);
startActivity(new Intent(this, OnboardingActivity.class));
} else {
startActivity(new Intent(this, MainActivity.class));
}
finish();
}
private boolean isFirstAppLaunch() {
SharedPreferences preferences = this.getPreferences(Context.MODE_PRIVATE);
return preferences.getBoolean(FIRST_APP_LAUNCH, true);
}
private void setFirstAppLaunch(boolean value) {
SharedPreferences preferences = this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(FIRST_APP_LAUNCH, value);
editor.apply();
}
}
I wonder What so tough in this. in the main Activity in the onCreate Method after checking the data starting another activity without setting the view content of Main Activity.
I have a problem with initializing my app properly after the autostart.
I've managed to get an autostart to work, after a reboot the app is shown as started but the timer's are not.
My guess is that the "onCreate" function of MyApp is not called when I call the context.startService(). The timers are set in the doActivity() function of MyApp.
I would greatly appreciate any tips on what I could be doing wrong or links to good tutorials. :)
The manifest:
<activity android:name=".MyApp"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="MyApp_Receiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>[/syntax]
MyApp_Receiver is a BoradcastReciever with the following two functions
public void onReceive(Context context, Intent intent) {
// Do Autostart if intent is "BOOT_COMPLETED"
if ((intent.getAction() != null) && (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")))
{
// Start the service
context.startService(new Intent(context, MyApp.class));
}
// Else do activity
else
MAIN_ACTIVITY.doActivity();
}
public static void setMainActivity(MyApp activity)
{
MAIN_ACTIVITY = activity;
}
MyApp extends PreferenceActivity and has an onCreate() and a doActivity(), the doActivity() reads out the preferences and sets a timer depending on them.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Show preferences
addPreferencesFromResource(R.xml.preferences);;
// Register Preference Click Listeners
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
// Prepare for one-shot alarms
if (mIntent == null)
{
mIntent = new Intent(MyApp.this, MyApp_Receiver.class);
mSender = PendingIntent.getBroadcast(MyApp.this,
0, mIntent, 0);
MyApp_Receiver.setMainActivity(this);
}
// Refresh and set all timers on start
doActivity();
}
The timers are set in the doActivity()
function of MyApp.
That will never work. MyApp is an activity, one that will not be created until the user goes in and launches it.
Read your SharedPreferences in onReceive() and set the alarms there.