2011年5月15日日曜日

MOTOROLA XOOM をAndroid OS 3.1にUpdate


やっとOTAがきました

私のXOOM (3G Verizon版)にSystem Updateの通知がきました。

f:id:baroqueworksdev:20110514153203p:image:w480



Update後の「About tablet」を確認すると、ビルドバージョンはHMJ37でした。



f:id:baroqueworksdev:20110514153202p:image:w480





widgetをLongPressすることでサイズ変更の枠が現れました。

青いひし形のマークをドラッグすることでサイズ変更ができました。

f:id:baroqueworksdev:20110514153606p:image:w480

2011年5月14日土曜日

アプリケーションが android:largeHeap=”true”指定されているかどうか確認する


ApplicationInfoの情報


AndroidManifest.xmlに情報を記述するってことは、その情報はApplicationInfoに格納されることは容易に想像がつくと思います。

デベロッパーサイトのApplicationInfoに以下の記載がありました。

public static final int FLAG_LARGE_HEAP

Since: API Level 11

Value for flags: true when the application has requested a large heap for its processes. Corresponds to android:largeHeap.

Constant Value: 1048576 (0x00100000)


ApplicationInfoのpublicメンバー、「flags」のフラグをチェックすれば判断できるってことですね。



MOTOROLA XOOMのインストールアプリを確認


以下のようにインストールアプリの情報を取得して、FLAG_LARGE_HEAPのフラグが立っているアプリのみログ出力してみました。

PackageManager pm = getPackageManager();
if(pm != null){
    List<PackageInfo> package_list = pm.getInstalledPackages(
                    PackageManager.GET_UNINSTALLED_PACKAGES );
    for (PackageInfo info : package_list){
        if(info.applicationInfo != null){
            if((info.applicationInfo.flags & ApplicationInfo.FLAG_LARGE_HEAP) != 0){
                Log.e("FLAG_LARGE_HEAP", info.packageName);
            }
        }
    }
}


結果は以下のアプリでした。

05-15 04:25:42.530: ERROR/FLAG_LARGE_HEAP(7592): com.android.launcher

05-15 04:25:42.530: ERROR/FLAG_LARGE_HEAP(7592): com.google.android.youtube
なんとなく納得できそうなアプリ達でした。




2011年5月13日金曜日

android:largeHeap=”true”で使用可能なHeapサイズ


アプリケーションで使用するHeapサイズを拡大する

APIレベル11(ハニカム)からアプリケーションで使用するHeapサイズを拡大できるらしい。

デベロッパーサイトに以下のような記載があります。

Return the approximate per-application memory class of the current device when an application is running with a large heap. This is the space available for memory-intensive applications; most applications should not need this amount of memory, and should instead stay with the getMemoryClass() limit. The returned value is in megabytes. This may be the same size as getMemoryClass() on memory constrained devices, or it may be significantly larger on devices with a large amount of available RAM.

The is the size of the application's Dalvik heap if it has specified android:largeHeap="true" in its manifest.


AndroidManifest.xmlに以下の記述をすると使用Heapサイズの拡大可能。
android:largeHeap="true"


ActivityManager.getLargeMemoryClass()でサイズを確認。
ActivityManager am = ((ActivityManager)getSystemService(Activity.ACTIVITY_SERVICE));
int largeMemory = am.getLargeMemoryClass();  


ためしに、Motorola Xoom(MZ600) Android OS 3.0で確認したところ、"256MB"でした。


(追記)
Android OS 3.1にUpdate後確認。
Motorola Xoom(MZ600) Android OS 3.1で確認したところ、"256MB"でした。

2011年5月7日土曜日

カスタムNotification Layoutについて


NotificationにカスタムRemoteViewsをセット

NotificationManagerに登録するオブジェクト・Notificationを次のようにすると、カスタムLayoutを表示することができます。


NotificationManager notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.icon, context.getString(R.string.app_name), 0);
notification.contentView = new RemoteViews(context.getPackageName(),YOUR_CUSTOM_LAYOUT_ID);


下の画像みたいな感じで表示できます。


f:id:baroqueworksdev:20110508020042p:image


各画像からIntentを発行したい

カスタムLayoutが表示できるとなると、次は「各画像をクリックしたら各アプリを起動」したくなります。
RemoteViewsは以下のように各ViewにPendingIntentをセットすることができます。

notification.contentView.setOnClickPendingIntent( VIEW_ID, pendingIntent);


しかし、結論からいうと、FroyoでもGingerBreadでもIntent起動は不可能でした。
(※ただしHTC端末は可能。Android OS 3.0から正式サポートされています)

以下のソースをみれば理解できると思いますが、Intentの発行処理はnotification.contentIntentのみ対象となっています。

\frameworks\base\services\java\com\android\server

  • StatusBarManagerService.java
  • NotificationManagerService.java


Android OS 3.0から正式サポート

各ViewのPendingIntentによる起動がAndroid OS 3.0から正式サポートされています。
デベロッパーサイト Android 3.0 Platform
Support for custom notification layouts to include buttons with PendingIntents, for more interactive notification widgets. For example, a notification can control music playback without starting an activity.


Motorola Xoomで確認すると次のような表示ができました。また、アイコンをクリックするとアプリ起動も可能でした。


f:id:baroqueworksdev:20110508032317p:image

2011年5月4日水曜日

自アプリ以外のアプリをclearDefaultできません

自アプリに対してのみclearDefault可能

PackageManagerクラスのclearPackagePreferredActivities()で各Actionの「デフォルトでの起動」を解除できます。
ただし、Developerサイトに以下の記載されている通り、自アプリに対してのみ使用可能です。"An application can only clear its own package(s)."


プログラムをみてみる

あまりframworkのソースコードまで追いかけるサイトがありませんが、あえて確認の意味で覗いてみます。
該当ソースコードは
\frameworks\base\services\java\com\android\server
 PackageManagerService.java


    public void clearPackagePreferredActivities(String packageName) {
        synchronized (mPackages) {
            int uid = Binder.getCallingUid();
            PackageParser.Package pkg = mPackages.get(packageName);
            if (pkg == null || pkg.applicationInfo.uid != uid) {
                if (mContext.checkCallingOrSelfPermission(
                        android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
                        != PackageManager.PERMISSION_GRANTED) {
                    if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
                            < Build.VERSION_CODES.FROYO) {
                        Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
                                + Binder.getCallingUid());
                        return;
                    }
                    mContext.enforceCallingOrSelfPermission(
                            android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
                }
            }

            if (clearPackagePreferredActivitiesLP(packageName)) {
                scheduleWriteSettingsLocked();            
            }
        }
    }



以下のソースでTargetSdkの確認を行い、Froyo以前の場合は問答無用でエラー扱い。
if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
        < Build.VERSION_CODES.FROYO) {


TargetSdkがFroyo以上でも、以下のソースでパーミッションやPidのチェックが行われ、SecurityExceptionとなります。

    private void enforce(
            String permission, int resultOfCheck,
            boolean selfToo, int uid, String message) {
        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException(
                    (message != null ? (message + ": ") : "") +
                    (selfToo
                     ? "Neither user " + uid + " nor current process has "
                     : "User " + uid + " does not have ") +
                    permission +
                    ".");
        }
    }


    public void enforceCallingOrSelfPermission(
            String permission, String message) {
        enforce(permission,
                checkCallingOrSelfPermission(permission),
                true,
                Binder.getCallingUid(),
                message);
    }

2011年5月3日火曜日

Settingsアプリのアプリケーション詳細画面を呼び出してみる

呼び出し方法

APIレベル9よりSettingsクラスに「ACTION_APPLICATION_DETAILS_SETTINGS」が追加されています。
Developerサイトより

Activity Action: Show screen of details about a particular application.
In some cases, a matching Activity may not exist, so ensure you safeguard against this.
Input: The Intent's data URI specifies the application package name to be shown, with the "package" scheme. That is "package:com.my.app".
Output: Nothing.
Constant Value: "android.settings.APPLICATION_DETAILS_SETTINGS"
IntentにはActionと表示したいアプリケーションのpackageスキームを指定します。
ソースコード上はこんな感じでしょうか。
(※actionの指定が直書きですが気にしないでください)


startActivityForResult(new Intent("android.settings.APPLICATION_DETAILS_SETTINGS",
                             Uri.parse("package:[起動したいアプリのPackageName]") )),0); 


2011年5月2日月曜日

検索キーでアプリ起動したい

やりたいこと

検索キー長押しで特定のActivityを起動したい。
デフォルトは音声検索が起動しますが、自分はあまり必要としないので、別のアプリを起動したい。


実現方法

AndroidManifest.xmlにintent-filterを記載すれば起動可能。
<intent-filter>
    <action android:name="android.intent.action.SEARCH_LONG_PRESS" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>