顯示具有 Android 標籤的文章。 顯示所有文章
顯示具有 Android 標籤的文章。 顯示所有文章

2012年6月7日 星期四

Android 4.0 CTS 設備設定


還是需以官方文件為準,只是有些部份我覺得寫得不是很清楚或是過時,可以參考看看!

1.確認裝置手機或平台是user-build

2.settings-->Backup & reset-->Factorydata reset

3.平台插入一張空的sd卡(沒有空的他也會把你刪掉)

4.平台安裝APK:CtsDelegatingAccessibilityService.apk,CtsDeviceAdmin.apk

5.settings打開Wi-Fi,並確定ap可連外

6.settings-->Security-->Screenlock-->None

7.settings-->Security-->Deviceadministrators-->Enable

8.settings-->Display-->Sleep-->30minutes或None

9.settings-->Accessibility-->EnableDelegating Accessibility Service

10.settings-->Developeroptions-->Enable USB debugging、Stay awake、Allowmock locations

11.開始測試前畫面需停留在Homescreen,並且不要有其他的task在跑,也不要任何操作。

2012年4月17日 星期二

螢幕鎖(Screen Lock)開啟/關閉

預設是開啟的,要關閉有兩個地方要改:

1. frameworks\policies\base\phone\com\android\internal\policy\impl\KeyguardViewMediator.java

  private boolean mExternallyEnabled = true;
  //set to false if you want disable Screen Lock

2. frameworks/base/packages/SettingsProvider/res/values/defaults.xml

 60000
 // set to -1 if you want disable Screen Lock

兩個都要設定才ok~

2012年3月8日 星期四

本地和設備間傳遞檔案

從設備取得檔案

adb pull /data/data/com.example.sample   ./sample/

從本機上傳檔案
adb push ./sample/  /sdcard/sample/

當然也可以用DDMS,但是有時候指令是方便許多~


參考

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的機制會比較安全~

2012年2月9日 星期四

如何移除與置換預設Launcher


如果想要把預設的Launcher給換掉,可以利用以下方法

使用adb工具,下以下指令:

adb remount

adb shell rm system/app/Launcher2.apk

adb uninstall com.android.launcher

adb install Launcher_xxx.apk (or use eclipse Run ..)

這樣就可以了喔~

Android如何找到最適合的資源檔

參考官方的說明:How Android Finds the Best-matching Resource


1. 消除和設備設定不符合的資源資料夾(qualifier),例如語言設定為en,就會把 fr-rCA消除掉
    drawable/
  drawable-en/
  drawable-fr-rCA/
  drawable-en-port/
  drawable-en-notouch-12key/
  drawable-port-ldpi/
  drawable-port-notouch-12key/

  例外:螢幕解析度在這個階段是唯一衝突但是不會刪的資源資料夾,例如device是hdpi但是ldpi還是會留著 。(想瞭解更多請參考Supporting Multiple Screens)

2.選擇下一個最高順位的qualifier
(最高是 MCC,MNC,Language...) 請參考這個table的順位 
3.有沒有符合的資料夾,沒有就回到上一步直到找到。
4.消除掉沒有最高順位qualifier的資源資料夾,例如:把沒有語言qualifier的資料夾都消掉。
  drawable/
  drawable-en/
  drawable-en-port/
  drawable-en-notouch-12key/
  drawable-port-ldpi/
  drawable-port-notouch-12key/
  例外:如果qualifier和螢幕解析度有不符合的狀況,Android會自動選擇最符合設備螢幕密度的qualifier,一般來說andorid會選擇把高解析度的圖檔給縮小,而不是把低解析度的讀檔給放大。
5.再回到2,直到刪到只剩下一個資源資料夾。





2012年2月8日 星期三

Android View ScrollBar 設定


WebView 和 GridView的ScrollBar 設定

.setVerticalScrollBarEnabled(false);  //取消Vertical ScrollBar顯示

.setHorizontalScrollBarEnabled(false); //取消Horizontal ScrollBar顯示

.setScrollBarStyle(View.SCROLLBARS_XXX) ;// 設定ScrollBar樣式

樣式請參考這裡

.setHorizontalScrollbarOverlay(boolean overlay);
//設定Horizontal ScrollBar是否覆蓋樣式

.setVerticalScrollbarOverlay(boolean overlay);
//設定 Vertical ScrollBar  ScrollBar是否覆蓋樣式




2011年10月5日 星期三

OpenGL ES for Android的學習(二):建立多邊形(polygon)

一般來說,學繪圖的HelloWorld應該是要來劃一個三角形(Triangle),下面我綜合參考了
Jayway Team Blog:OpenGL ES Tutorial for Android –Part II– Building a polygon
3D Graphics using OpenGL ES (Including Nehe's Port)Example 2
來完成建立多邊形這個教學!

在開始建立程式前,先補充說明在建立3D模型時,需要用到的一些子元素
(頂點表面多邊形),他們都能獨立的分別被實做出來。
  • 頂點(Vertex)
         頂點是構成3D模型的最小建物,他是由兩個或兩個以上的邊交界而成的點。一個頂點可以在所有相關聯的邊、面和多邊形中共用。頂點也可以是照相機或光源位置的表示。Android中,我們浮點數陣列來定義它,同時我們將它放在byte buffer中以獲取較佳的效能。

 private float vertices[] = {  
    -1.0f, 1.0f, 0.0f, // 0, Top Left  
    -1.0f, -1.0f, 0.0f, // 1, Bottom Left  
     1.0f, -1.0f, 0.0f, // 2, Bottom Right  
     1.0f, 1.0f, 0.0f, // 3, Top Right  
 };  
 // a float is 4 bytes, therefore we multiply the number if vertices with 4.  
 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);  
 vbb.order(ByteOrder.nativeOrder());  
 FloatBuffer vertexBuffer = vbb.asFloatBuffer();  
 vertexBuffer.put(vertices);  
 vertexBuffer.position(0);  
要注意的一個浮點數是4個位元組,將它和頂點數相乘,才可以正確的配置buffer大小。
  • (Edge)
          邊是在兩個頂點之間的線段。它們是表面和多邊形的邊緣線。在3D模型中,便可以在       兩個鄰近表面或多邊形之間共用。轉換一條邊,影響所有相連接的頂點,面和多邊形 。OpenGL ES中,我們不能定義邊,你只能通過給定的頂點定義面,這將至少構建三條邊。如果你想要修改一條邊,你應該改變產生這條邊的兩個頂點。
  • (face)
          面是一個三角形,面就是這三個頂點和三個邊所圍成的表面,變換一個面影響所有關聯         的頂點,邊和多邊形。對於這些元素的介紹先到這裡,Jayway還有一些細部的介紹,都還蠻有價值的,但我相信大家沒看到code就很難過,我們就先來畫畫三角形吧!          


Triangle.java
 com.hanshuo.opengl.tutorial;  
 import java.nio.ByteBuffer;  
 import java.nio.ByteOrder;  
 import java.nio.FloatBuffer;  
 import javax.microedition.khronos.opengles.GL10;  
 /*  
  * A triangle with 3 vertices.  
  */  
 public class Triangle {  
   private FloatBuffer vertexBuffer; // 頂點陣列的緩衝  
   private ByteBuffer indexBuffer;  // 索引緩衝  
   private float[] vertices = { // 三角形的頂點們  
     0.0f, 1.0f, 0.0f, // 0. 頂  
    -1.0f, -1.0f, 0.0f, // 1. 左下  
     1.0f, -1.0f, 0.0f // 2. 右下  
   };  
   private byte[] indices = { 0, 1, 2 }; // 連結這些點的順序  
   // 建構子 – 建立資料陣列的緩衝  
   public Triangle() {  
    // 建立頂點陣列緩衝. 頂點是浮點數要乘4個byte.  
    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);  
    vbb.order(ByteOrder.nativeOrder()); // 使用原生順序  
    vertexBuffer = vbb.asFloatBuffer(); // 轉換位元組緩衝為浮點數  
    vertexBuffer.put(vertices);     // 將資料複製到緩衝  
    vertexBuffer.position(0);      // 倒轉歸零  
    //建立頂點索引陣列緩衝
    indexBuffer = ByteBuffer.allocateDirect(indices.length);  
    indexBuffer.put(indices);  
    indexBuffer.position(0);  
   }  
   // 渲染這個圖形  
   public void draw(GL10 gl) {  
    // Enable vertex-array and define the buffers  
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);  
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);  
    // int size, int type, int stride, Buffer pointer  
    // size: 頂點的座標數 (只有2,3,4).  
    // type: 頂點座標的資料型態, GL_BYTE, GL_SHORT, GL_FIXED, or GL_FLOAT  
    // stride: 連續頂點可以有幾個byte的offset. 0是緊密的包裝?  
    // 透過index-array繪製元素
    gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);  
    // int mode, int count, int type, Buffer indices) 
    // mode: GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, or GL_TRIANGLES  
    // count: 有幾個元素將要被渲染 
    // type:頂點的資料型態 (must be GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT).  
    // indices:index array的指標   
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);  
   }  
 }  

TutorialPartI.java (藍色是新的程式碼)
 package com.hanshuo.opengl.tutorial;  
 import javax.microedition.khronos.egl.EGLConfig;  
 import javax.microedition.khronos.opengles.GL10;  
 import android.content.Context;  
 import android.opengl.GLU;  
 import android.opengl.GLSurfaceView.Renderer;  
 public class OpenGLRenderer implements Renderer {  
      Triangle triangle;   
      public OpenGLRenderer() {  
         // Set up the data-array buffers for these shapes (多了這裡)  
         triangle = new Triangle();  // (多了這裡)   
        }  
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
           // 將背景設成紅色 (rgba).  
           gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);  
           // 允許陰影平滑, 預設也可以,不是必須的  
           gl.glShadeModel(GL10.GL_SMOOTH);  
           // 深度緩衝設置  
           gl.glClearDepthf(1.0f);  
           // 允許深度測試  
           gl.glEnable(GL10.GL_DEPTH_TEST);  
           // 深度檢測類型  
           gl.glDepthFunc(GL10.GL_LEQUAL);  
           // 精細度設置  
           gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);  
      }  
      public void onDrawFrame(GL10 gl) {  
           // 清除螢幕和深度緩衝  
           gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);       
           gl.glLoadIdentity();         // Reset model-view matrix (多了這裡)
           gl.glTranslatef(-1.5f, 0.0f, -6.0f); // Translate left and into the screen (多了這裡)  
           triangle.draw(gl);          // Draw triangle (多了這裡)      
      }  

執行結果:

有沒有很簡單捏~

2011年10月4日 星期二

OpenGL ES for Android的學習(一):基礎概念

Android對於OpenGL的支援,可以透過frameworkAPINDK兩種,這裡要教學的是前者。GLSurfaceViewGLSurfaceView.RendererOpenGL ES API中最基礎了兩個類別,透過它你可以創造與操作影像。如果你的目標是將OpenGL應用在你的App,瞭解如何在activity中實作這些類別是第一要務。

l   GLSurfaceView (Class Link)
顧名思義,他是View的一種,你可以透過OpenGL API呼叫它,你可以對它畫圖(draw)和作其他操作,功能上和SurfaceView是很類似的。
它主要的特徵有:
n   管理一個surface:它是在記憶體中的特別區塊,能夠被覆合成為AndroidView
n   管理一個EGL:使OpenGL能夠render(對岸通常稱之為"渲染")到一個surface.
n   讓使用者自訂的render物件能夠被使用。
n   render的工作可以透過獨立單一的執行緒,和UI分開,以增進效能與平滑度。
n   支援自訂的或持續性的渲染。
n   提供易於使用的debug工具,來追蹤opengl es API的呼叫。

  如果你想要有觸控的功能,要自己延伸touch listeners
  可以參考TouchRotateActivity

l   GLSurfaceView.Renderer(Class Link)
這個介面定義了用來在GLSurfaceView上繪圖的方法,我們必須在另一個單獨的類別來實做這個介面,然後再用GLSurfaceView.setRenderer()的方式附加在GLSurfaceView的實例(instance)上。
GLSurfaceView.Renderer介面需要實作以下幾個方法:
n   onSurfaceCreated():這個方法在創造GLSurfaceView時只會被系統呼叫一次,像是設定OpenGL的環境參數或是初始化OpenGL繪圖物件都是在這裡。
n   onDrawFrame():當系統每次要重新繪圖(redraw)時會呼叫這個方法,此為物件繪圖(重繪)的主要方法。
n   onSurfaceChanged():GLSurfaceView在幾何上有改變時,系統會呼叫這個方法,包含GLSurfaceView的大小改變或是設備螢幕大小的改變。像是設備將顯示從直立改成橫立時,系統就會呼叫它。請這個方法來回應與處理GLSurfaceView的改變。

接著要來貼Code了,只需要兩支:

TutorialPartI.java
 package com.hanshuo.opengl.tutorial;  
 import android.app.Activity;  
 import android.opengl.GLSurfaceView;  
 import android.os.Bundle;  
 import android.view.Window;  
 import android.view.WindowManager;  
 public class TutorialPartI extends Activity {  
   /** Called when the activity is first created. */  
   @Override  
   public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        this.requestWindowFeature(Window.FEATURE_NO_TITLE); //不要標題  
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
       WindowManager.LayoutParams.FLAG_FULLSCREEN);//全螢幕  
            GLSurfaceView view = new GLSurfaceView(this);  
             view.setRenderer(new OpenGLRenderer());  
             setContentView(view);  
   }  
 }  
OpenGLRenderer.java
 package com.hanshuo.opengl.tutorial;  
 import javax.microedition.khronos.egl.EGLConfig;  
 import javax.microedition.khronos.opengles.GL10;  
 import android.opengl.GLU;  
 import android.opengl.GLSurfaceView.Renderer;  
 public class OpenGLRenderer implements Renderer {  
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
           // 將背景設成紅色 (rgba).  
           gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);  
           // 允許陰影平滑, 預設也可以,不是必須的  
           gl.glShadeModel(GL10.GL_SMOOTH);  
           // 深度緩衝設置  
           gl.glClearDepthf(1.0f);  
           // 允許深度測試  
           gl.glEnable(GL10.GL_DEPTH_TEST);  
           // 深度檢測類型  
           gl.glDepthFunc(GL10.GL_LEQUAL);  
           // 精細度設置  
           gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);  
      }  
      public void onDrawFrame(GL10 gl) {  
           // 清除螢幕和深度緩衝  
           gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);            
      }  
      public void onSurfaceChanged(GL10 gl, int width, int height) {  
           // 把View設定到符合新的(螢幕)大小  
           gl.glViewport(0, 0, width, height);  
           // 選擇投影的矩陣  
           gl.glMatrixMode(GL10.GL_PROJECTION);  
           // 重設投影的矩陣  
           gl.glLoadIdentity();  
           // 計算視窗的比例  
           GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,  
                     100.0f);  
           // 選擇modelview矩陣  
           gl.glMatrixMode(GL10.GL_MODELVIEW);  
           // 重設modelvew矩陣  
           gl.glLoadIdentity();  
      }  
 }  

這樣就算完成一支:Andorid OpenGL ES的"Hello World!"了!

應該不用貼圖吧,就看你背景是設什麼顏色,我這範例就會看到一片紅!