2012-11-02 52 views
32

我正在審查Google I/O Session 2012 app和整個這個TODO如何定義那些僅用於手機或平板電腦在Android

// 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來到活動。

回答

45

我想出了這個辦法(注:這是Google I/O Session 2012 app UIUtilis.java模仿):

AndroidManifest.xml定義Activity s到包括<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將始終返回爲空。

最後觸摸是調用此方法,有可能在的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); 
} 

現在你可以有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();應該是向後兼容過去API 12.

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)。並在上面的代碼中進行了所有更改。

+0

感謝您的回答。但爲什麼讓它成爲社區維基? –

+0

我以爲Application.onCreate比Activity.onCreate更合適..? –

+0

@ android.weasel「很可能在onCreate ...」,如果你有另一個位置適合你,就去做吧。這只是簡單地實施來自iosched應​​用程序的「TODO」以使用標籤。把它放在'Activity'中是一件好事,你不需要擴展'Application'類來完成它。 –

相關問題