7

I am creating an application for Android 4.0+, and I want to achieve this behavior. Two different activities will have two launcher icons when the user's device is a phone, and it will be just one (the activities will consist of fragments that I will display as tabs in one main activity) on tablet devices. I know that one can set up multiple launcher activities in the manifest, but I think that maybe I would need something that will determine this operation during runtime (in java code).

Kara
  • 6,115
  • 16
  • 50
  • 57
Sandra
  • 4,239
  • 10
  • 47
  • 80

5 Answers5

12

Two different activities will have two launcher icons when the user's device is a phone, and it will be just one (the activities will consist of fragments that I will display as tabs in one main activity) on tablet devices.

There is no concept in Android of "phone" and "tablet". I am going to assume that you are distinguishing between "phone" and "tablet" in terms of screen size.

If that is true:

Step #1: Create a res/values/bools.xml file and define two <bool> resources, is_phone and is_tablet. Have is_phone be true and is_tablet be false.

Step #2: Create a res/values-.../bools.xml file, where ... is whatever qualifier you are using with your layouts to distinguish between "phones" and "tablets" (e.g., -large, -xlarge, -swNNNdp). Define the same two <bool> resources there with opposite values (i.e., is_phone is false, is_tablet is true).

Step #3: Add both activities to your manifest, each set up for the MAIN/LAUNCHER <intent-filter>. On the one you want to use on a "phone", add android:enabled="@bool/is_phone" to the <activity> element. On the one you want to use on a "tablet", add android:enabled="@bool/is_tablet" to the <activity> element.

This way, based on the same rules that you are using for your layouts, you will have a different launcher activity.


Apparently, this doesn't work, though I swear it used to.

Another option is to have a single activity be the MAIN/LAUNCHER one. Have it set up with android:theme="@style/Theme.NoDisplay", so it does not have a UI. Have it make the determination, in Java, in onCreate(), which of your "real" entry-point activities is appropriate for the given screen size, perhaps using the same bool resources I cited above. Have it then call startActivity() to pass control to the right activity and call finish() on itself (so the user does not encounter an invisible activity on the BACK stack). This technique is also used in cases where there is no way to control this via the manifest, such as "do we have Maps V1 or not" where you have android:required="false" on the <uses-library> element.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • That seems like an interesting solution. I did not know about the 'enabled' attribute that can be set up in the manifest for activities. I will definitely try this out. Thank u! – Sandra May 15 '13 at 08:22
  • I did as u suggested, but sth is not working for me. Due to the above mentioned behavior that i want to achieve, I set up two resources in bools.xml files (bools.xml in res/values and bools.xml in res/values-sw600dp) = > main_activity_enabled (true in res/values and true in res/values-sw600dp), second_activity_enabled (true in res/values and false in res/values-sw600dp). From this I should have ONLY MainActivity as launcher on tablet devices, but despite that I have two launchers :S – Sandra May 15 '13 at 09:34
  • @Sandra: You need `main_activity_enabled` to be `false` in one of your cases -- you claim to have it be `true` in both. – CommonsWare May 15 '13 at 10:35
  • Yes, because I want MainActivity to be launcher for tablets, and MainAcitivity and SecondActivity to be both launchers for phones. But is seems that this can not be done :s http://stackoverflow.com/questions/14399292/is-selectively-enabling-an-activity-alias-in-the-manifest-with-androidenabled . I tried exactly what you suggested also, it did not work. – Sandra May 15 '13 at 10:39
  • @Sandra: Hmmmmm... OK. I have edited my answer with another solution. – CommonsWare May 15 '13 at 10:55
  • Thank u again for your other option, but that seems that will produce only one launcher on both phones and tablets (with the possibility to start different activity if the device is a tablet or a phone). But the problem is that I need, one launcher on tablet, and two on phones.. :s The first option was really good, only if it worked.. – Sandra May 16 '13 at 08:35
1

Why to take so much pain? Just go about designing separate apps for phone and tablet (make sure they have the same package name). Multiple APKs is what you should look for:

Although we encourage you to develop and publish a single APK that supports as many device
configurations as possible, doing so is sometimes not possible. To help you publish your
application for as many devices as possible, Google Play allows you to publish multiple 
APKs under the same application listing. Google Play then supplies each APK to the 
appropriate devices based on configuration support you've declared in the manifest file of 
each APK. 

Here's a link: http://developer.android.com/google/play/publishing/multiple-apks.html

Vikram Gupta
  • 6,496
  • 5
  • 34
  • 47
  • I already started developing my application with a single apk for both phones and tablets. My hole application logic is based on that. Now I need to add new activity, with this behavior. So I need sth that can make my activity - launcher activity in code :s – Sandra May 14 '13 at 09:59
  • use only one activity launcher and in onCreate before setContent just check whether the device is a phone or a tablet (by calculating screen size). After that set the desired xml as the content for the activity. – Vikram Gupta May 14 '13 at 10:06
  • Thx for the suggestion, but I am already using that in my application. Now I need to display a fragment as a tab on tablets, and encapsulated in separate launcher activity on phones. I think there must be a way to do this. – Sandra May 14 '13 at 10:42
1

On first launch of your application, you can programmatically check if your device is a tablet or phone. If it is a phone, you can programmatically add a shortcut to the home screen, and specify the Intent the launcher should use, in order to go to the correct Activity.

First, in your Manifest, you will have only one launcher, but you will have an Activity with no intent filters that will be opened from the programmatically-created shortcut.

Next, in your launcher Activity's onCreate, check if the you have already created the shortcut. From what I have read, the best way to do this is using a boolean value in SharedPreferences:

SharedPreferences prefs = getSharedPreferences(getPackageName(), MODE_PRIVATE);
if (!prefs.getBoolean("shortcut", false)) {
    if (!isTablet(this)) {
        createShortcut();
    }
    prefs.edit().putBoolean("shortcut", true).commit();
}
else {
    //if the shortcut has already been made, see if that is what was used to open this app
    if (getIntent() != null) {
        if (getIntent().getBooleanExtra("shortcut", false)) {
            //the shortcut was used, so open the other Activity:
            Intent shortcut = new Intent(this, OtherActivity.class);
            startActivity(shortcut);
        }
    }
}

Next, you need to define what you call a tablet. This is based on the density-independent pixels of the screen. For example, to call devices with 7-inch screens tablets, this number is 600. For larger devices - such as a 10-inch screen, this number is 720. Store this number in a variable:

private static final int TABLET_DP = 600;

Then add the methods used above:

public static boolean isTablet(Context context) {
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);\
    Display display = wm.getDefaultDisplay();
    DisplayMetrics outMetrics = new DisplayMetrics();
    display.getMetrics(outMetrics);
    float density  = context.getResources().getDisplayMetrics().density;
    float dpWidth  = outMetrics.widthPixels / density;
    return dpWidth >= TABLET_DP;
}

private void createShortcut() {

    //this is the intent that will be used when the shortcut is clicked.
    Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
    shortcutIntent.setClassName(this, this.getClass().getName());
    shortcutIntent.putExtra("shortcut", true);

    //this is the intent used to create the shortcut.
    Intent intent = new Intent();
    intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getString(R.string.app_name));//or however you want the shortcut to be labeled.
    Parcelable iconResource = Intent.ShortcutIconResource.fromContext(
            this,  R.drawable.ic_launcher);//or whatever you want the icon to be
    intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
    intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");

    //tell Android to create the shortcut
    context.sendBroadcast(intent);
}

Finally, be sure you have the correct permissions to install shortcuts:

<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"></uses-permission>
Phil
  • 35,852
  • 23
  • 123
  • 164
0

I may be beating a dead horse here, but what about using layout aliases?

Use Layout Aliases

wileyCoyote
  • 829
  • 5
  • 8
-1

You will need to make multiple apks, one for tabs and one for phones, the only difference will be the manifest file in those apks. Rest you can manage with code.

Aman Gautam
  • 3,549
  • 2
  • 21
  • 25