2012年3月4日 星期日

安裝程式按安裝時間排序

結合「取得安裝程式列表」和「取得安裝程式時間」這兩個功能就可以完成。

取得安裝程式列表:
private void bindAllApps() {
        
        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        mAllApps = mPackageManager.queryIntentActivities(mainIntent, 0);    
        sortappInstalledTime(mAllApps);
    }

根據安裝時間排序:
public void sortappInstalledTime(List<ResolveInfo> mAllApps2) {
        Collections.sort(mAllApps2, new Comparator<Object>() {
            public int compare(Object o1, Object o2) {
                ResolveInfo p1 = (ResolveInfo) o1;
                ResolveInfo p2 = (ResolveInfo) o2;
                Date d1 = getInstallTime(p1.activityInfo.packageName);
                Date d2 = getInstallTime(p2.activityInfo.packageName);

                if (d1 != null && d2 != null) {
                    if (d1.after(d2)) {
                        return -1;
                    } else if (d1 == d2) {
                        return 0;
                    } else {
                        return 1;
                    }
                } else {
                    return 1;
                }
            }
        });
    }

取得安裝時間:
    public Date getInstallTime(String packageName) {
        PackageManager pkgMgt = this.getPackageManager();
        return firstNonNull(installTimeFromPackageManager(pkgMgt, packageName),
                apkUpdateTime(pkgMgt, packageName));
    }

    private Date apkUpdateTime(PackageManager packageManager, String packageName) {

        try {
            android.content.pm.ApplicationInfo info = packageManager
                    .getApplicationInfo(packageName, 0);
            File apkFile = new File(info.sourceDir);
            return apkFile.exists() ? new Date(apkFile.lastModified()) : null;
        } catch (NameNotFoundException e) {
            return null; // package not found
        }
    }

    private Date installTimeFromPackageManager(PackageManager packageManager,
            String packageName) {
        try {
            PackageInfo info = packageManager.getPackageInfo(packageName, 0);
            Field field = PackageInfo.class.getField("firstInstallTime");
            long timestamp = field.getLong(info);
            return new Date(timestamp);
        } catch (NameNotFoundException e) {
            return null; // package not found
        } catch (IllegalAccessException e) {
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
        } catch (SecurityException e) {
        }
        // field wasn't found
        return null;
    }

            private Date firstNonNull(Date... dates) {
                for (Date date : dates)
                    if (date != null)
                        return date;
                return null;
            }

20120702補充:
後來發現,如果你像我一樣是要迴圈取得多個apk來排序的話,這樣的方式效能很x。可改用uid來排序,可以達到一樣的效果。
根據uid大小排序:
public void sortappByUid(List<ResolveInfo> mAllApps2) {
        Collections.sort(mAllApps2, new Comparator<ResolveInfo>() {
            public int compare(ResolveInfo o1, ResolveInfo o2) {
                ResolveInfo r1 = (ResolveInfo) o1;
                ResolveInfo r2 = (ResolveInfo) o2;
                int uid1 = r1.activityInfo.applicationInfo.uid;
                int uid2 = r2.activityInfo.applicationInfo.uid;

                
                    if (uid1>=uid2) {
                        return -1;
                    } else if (r1 == r2) {
                        return 0;
                    } else {
                        return 1;
                    }
                
            }
        });
    }

2012年2月16日 星期四

GridView Null Pointer Exception

error log:
 W/dalvikvm( 727): threadid=1: thread exiting with uncaught exception (group=0x2aac47e8)  
 E/AndroidRuntime( 727): FATAL EXCEPTION: main  
 E/AndroidRuntime( 727): java.lang.NullPointerException  
 E/AndroidRuntime( 727):    at android.widget.GridView.setupChild(GridView.java:1246)  
 E/AndroidRuntime( 727):    at android.widget.GridView.makeAndAddView(GridView.java:1222)  
 E/AndroidRuntime( 727):    at android.widget.GridView.makeRow(GridView.java:265)  
 E/AndroidRuntime( 727):    at android.widget.GridView.fillDown(GridView.java:218)  
 E/AndroidRuntime( 727):    at android.widget.GridView.fillSpecific(GridView.java:482)  
 E/AndroidRuntime( 727):    at android.widget.GridView.layoutChildren(GridView.java:1122)  
 E/AndroidRuntime( 727):    at android.widget.AbsListView.onLayout(AbsListView.java:1147)  
 E/AndroidRuntime( 727):    at android.view.View.layout(View.java:7085)  
 E/AndroidRuntime( 727):    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:909)  
 E/AndroidRuntime( 727):    at android.view.View.layout(View.java:7085)  
 E/AndroidRuntime( 727):    at android.widget.AbsoluteLayout.onLayout(AbsoluteLayout.java:120)  
 E/AndroidRuntime( 727):    at android.view.View.layout(View.java:7085)  
 E/AndroidRuntime( 727):    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)  
 E/AndroidRuntime( 727):    at android.view.View.layout(View.java:7085)  
 E/AndroidRuntime( 727):    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)  
 E/AndroidRuntime( 727):    at android.view.View.layout(View.java:7085)  
 E/AndroidRuntime( 727):    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)  
 E/AndroidRuntime( 727):    at android.view.View.layout(View.java:7085)  
 E/AndroidRuntime( 727):    at android.view.ViewRoot.performTraversals(ViewRoot.java:1045)  
 E/AndroidRuntime( 727):    at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)  
 E/AndroidRuntime( 727):    at android.os.Handler.dispatchMessage(Handler.java:99)  
 E/AndroidRuntime( 727):    at android.os.Looper.loop(Looper.java:123)  
 E/AndroidRuntime( 727):    at android.app.ActivityThread.main(ActivityThread.java:4627)  
 E/AndroidRuntime( 727):    at java.lang.reflect.Method.invokeNative(Native Method)  
 E/AndroidRuntime( 727):    at java.lang.reflect.Method.invoke(Method.java:521)  
 E/AndroidRuntime( 727):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)  
 E/AndroidRuntime( 727):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)  
 E/AndroidRuntime( 727):    at dalvik.system.NativeStart.main(Native Method)  
log有點難看出是哪段程式碼出了問題,只知道GridView出了問題,通常這種問題都是出現在getView的時候回傳null值產生,所以一定要避免漏接了null的View
 if (xxxView = = null)  
  {  
    ...  
 }   
參考網址

2012年2月15日 星期三

提高背景圖的設定

在一般手機螢幕的圖檔,其實解析度稍微低一些,並不會太明顯。
但是在電視的環境就會要更高的要求。
因此要求出圖的設計師都要提供32bit圖檔。
但是android預設的解析度是 RGB_565,因此要另外更改設定成ARGB_8888才行,否則會有color loss的狀況。


我的狀況是在背景圖,可以用下面的code來設定。
Code:

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;   
        Bitmap myBitmap =BitmapFactory.decodeResource(mContext.getResources(),R.drawable.m_background,options);  
        BitmapDrawable bd = new BitmapDrawable(this.getResources(), myBitmap);
        youview.setBackgroundDrawable(bd);


當然,為大幅增加記憶體用量,要同時使用gc的機制會比較安全~