32

Google I / O Session 2012アプリを確認していて、このTODOに出くわしました

// TODO: use <meta-data> element instead
private static final Class[] sPhoneActivities = new Class[]{
        MapActivity.class,
        SessionDetailActivity.class,
        SessionsActivity.class,
        TrackDetailActivity.class,
        VendorDetailActivity.class,
};

// TODO: use <meta-data> element instead
private static final Class[] sTabletActivities = new Class[]{
        MapMultiPaneActivity.class,
        SessionsVendorsMultiPaneActivity.class,
};

public static void enableDisableActivities(final Context context) {
    boolean isHoneycombTablet = isHoneycombTablet(context);
    PackageManager pm = context.getPackageManager();

    // Enable/disable phone activities
    for (Class a : sPhoneActivities) {
        pm.setComponentEnabledSetting(new ComponentName(context, a),
                isHoneycombTablet
                        ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                        : PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }

    // Enable/disable tablet activities
    for (Class a : sTabletActivities) {
        pm.setComponentEnabledSetting(new ComponentName(context, a),
                isHoneycombTablet
                        ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }
}

そのTODOをどうやって実行するのだろうと思いました。

4

1 に答える 1

45

私はこのアプローチを思いつきました(注:これはGoogle I / O Session 2012アプリUIUtilis.javaをモデルにしています):

AndroidManifest.xml定義に:Activityを含める<meta-data>

<!-- Note: specify the target device for Activities with target_device meta-data of "universal|phone|tablet"
           see UIUtils.java (configureDeviceSpecificActivities) for more details. -->

<!-- Activities for both phones and tablets -->
<activity android:name=".ui.AccountActivity" 
          android:configChanges="orientation|keyboardHidden" 
          android:label="@string/app_name"
          android:theme="@style/Theme.Accounts">
          <meta-data android:name="target_device" android:value="universal"/>
</activity>

<!-- Activities for tablets -->
<activity android:name=".ui.CoolMultipaneActivity"
          android:label="@string/app_name">
          <meta-data android:name="target_device" android:value="tablet"/>

大変な作業がメソッドに入れられますconfigureDeviceSpecificActivities(Context context)

/**
 * Enables and disables {@linkplain android.app.Activity activities} based on their "target_device" meta-data and
 * the current device. Add <meta-data name="target_device" value="tablet|phone|universal" /> to an activity to
 * specify its target device.
 * @param context the current context of the device
 * @see #isHoneycombTablet(android.content.Context)
 */
public static void configureDeviceSpecificActivities(Context context) {
    final PackageManager package_manager = context.getPackageManager();
    final boolean is_honeycomb_tablet = isHoneycombTablet(context);
    try {
        final ActivityInfo[] activity_info = package_manager.getPackageInfo(context.getPackageName(),
                PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA).activities;
        for (ActivityInfo info : activity_info) {
            final String target_device = info.metaData.getString("target_device");
            if (target_device == null) break;
            target_device = target_device.toLowerCase(Locale.US);
            final boolean is_for_tablet = target_device.equals("tablet");
            final boolean is_for_phone = target_device.equals("phone");
            final String class_name = info.name;
            package_manager.setComponentEnabledSetting(new ComponentName(context, Class.forName(class_name)),
                    is_honeycomb_tablet && is_for_phone
                            ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                            : !is_honeycomb_tablet && is_for_tablet
                            ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                            : PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                    PackageManager.DONT_KILL_APP);
        }
    } catch (PackageManager.NameNotFoundException error) {
        Ln.w(error.getCause());
    } catch (ClassNotFoundException error) {
        Ln.w(error.getCause());
    }
}

おもしろい事実:GET_META_DATAフラグがないと機能しませんmetaData。そのタグを含めないと、は常にnullとして返されるからです。

onCreate最後の仕上げは、おそらく最初のメソッドでこのメソッドを呼び出すことですActivity

@Override
protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);

    // Anything else you want to do in the onCreate callback

    // Set up to use the appropriate Activities for the given device
    UIUtils.configureDeviceSpecificActivities(this);
}

これで、レイアウトを変更するだけで、さらに多くのsを含めるだけでは不十分なActivity場合に備えて、携帯電話やタブレット用に特別に設計されたsを使用できます。Fragment

注:警告が表示された場合は、そうする必要final String class_name = info.packageName + info.name;がある場合があります。final String class_name = info.name;

注(2):final String target_device = info.metaData.getString("target_device", "").toLowerCase();API12以降の下位互換性のために使用する必要があります。

String target_device = info.metaData.getString("target_device");
if (target_device == null) break;
target_device = target_device.toLowerCase();

注(3):target_device.toLowerCase();デフォルトのロケールを暗黙的に使用します。target_device.toLowerCase(Locale.US)代わりに使用してください。そして、上記のコードにすべての変更を加えました。

于 2012-11-02T20:45:15.583 に答える