2012年5月20日 星期日

[AndroidDev] Managing the Activity Lifecycle

  • 如果 AndroidManifest.xml 中沒有任何 activity 有宣告 MAIN action 與 LAUNCHER category,此 app 的 launch icon 則不會出現在 app list 中。
  • onPause <-> onResume
  • onStop -> onRestart -> onStart -> onResume

onCreate()
  • 適合處理在整個 activity life 中只應處理一次的邏輯,ex: 初始化 class-scope variables。

onRestart()
  • 當 activity 是從 onStop() 被啟動時,系統才會呼叫此 method。所以若是有在 onStop() 中釋放資源,記得在此初始或設定。

onStart()
  • activity 已為可見狀態,但會很快的便進入 onResume()。

onResume()
  • 會停留到 resume 完 activity 到暫停前的狀態。

onPause()
  • activity 仍為半可視狀態,ex: 被 dialog 覆蓋。
  • 可表示 user 離開此 activity 而進入 onStop(),所以可執行:
    • Stop animations or other ongoing actions that could consume CPU.
    • Commit unsaved changes, but only if users expect such changes to be permanently saved when they leave (such as a draft email).
    • Release system resources.
      • broadcast receivers, handles to sensors (like GPS).
      • Any resources that may affect battery life while your activity is paused and the user does not need them.
  • 不需要在此儲存 user 所輸入的資料,因為其實此 Activity instance 還是被儲存在 memory 中的,所以當在 onResume(),元件的狀態會再被重新載入,除非這是項明確功能:
    • ex: email 會自動儲存為草槁。
  • 不適合在此中處理會耗費 CPU 的工作,ex: 寫入 DB,因為會拖慢顯現下一個 activity 的速度,所以這類型的工作更適合在 onStop() 中處理。
    • 要到 activity B 前,activity A 需先進入 onPause()。

onStop()
  • 保證 UI 不是可視的,user 已在使用另一個 activity 或 app。
  • 適合做耗費 CPU 的工作:
    • ex: 寫入 DB。
  • 不需要在此儲存 user 所輸入的資料,因為其實此 Activity instance 還是被儲存在 memory 中的,所以當 onResume(),元件的狀態會再被重新載入。
    • ex: If the user entered text into an EditText widget, that content is retained so you don't need to save and restore it.
    • 即使 activity 被 destroy,其中的 View objects 仍會被儲存在 Bundle 中,並且在 user 回到此 activity(the same instance of the activity) 時被重新載入。
  • 以下情況使得 activity A 會被 stopped 與 restarted:
    • user 由 Recent Apps window 開啟另一個 app,activity A 會進入 onStop(),若 user 再由 Home launcher icon or Recent Apps window 開啟你的 app,那麼 activity A 會進入 onRestart()。
    • 在你的 app 中進入下一個 activity,activity A 會進入 onStop(),若 user 按下 Back 鍵,activity A 會進入 onRestart()。
    • user 在使用 app 時有來電。

onDestroy()
  • The system calls onDestroy() after it has already called onPause() and onStop() in all situations except one:
    • when you call finish() from within the onCreate() method.
    • onCreate() 會直接進入 onDestroy()。

以下情況可能會使得你的 activity 被 destroyed:
  • The user presses the Back button.
  • Calling finish().
  • Activity is in onStop() 且已長時間沒有被使用而被系統回收。
  • Foreground activity 需要更多資源,因此關閉 background processes to recover memory。

若 activity 是被系統回收,那麼系統會記下它的狀態(is called the "instance state", stored in a Bundle object.),以在 user 想開啟此 activity 時能 restore 該狀態。

onSaveInstanceState()
  • 當系統要 destroy this activity,會呼叫此 method,並且傳入 Bundle object 來儲存 activity 資訊,所以你若有需要保存的資訊也可儲存在此 Bundle 中。
  • 然後此 activity 會被系統 recreate 並且傳入與 destroy 時相同的 Bundle object,因此可以在 onCreate() 中從 Bundle 中取出之前所儲存的資訊。
    • 但因為 activity 可以是完全新建立或是重新被建立的,也就是說傳入的 Bundle 不一定都是有值的,若是要使用,務必判斷是不是 null。
    • 或者與其在 onCreate() 中 restore 資訊,也可以選擇在 onRestoreInstanceState() 做。
      • 此 method 會在 onStart() 後被呼叫。
      • 只有在 Bundle != null 時會被呼叫。
  • The default implementation of this method saves information about the state of the activity's view hierarchy:
    • ex: he text in an EditTextwidget or the scroll position of a ListView. 
    • 所以在此 method 和 onRestoreInstanceState() 中記得呼叫 super.xxxx; 以儲存與重載 the state of the view hierarchy。


* Reference
- Starting an Activity | Android Developers
- Pausing and Resuming an Activity | Android Developers
- Stopping and Restarting an Activity | Android Developers
- Recreating an Activity | Android Developers

[AndroidLayout] Input Method Editors

若沒有做任何設定與調整,在輸入時所跳出的鍵盤(IMEs, Input Method Editors)很有可能會擋住正在輸入文字的元件,可以用以下方式處理:
  • 畫面中使用 scrollView,讓使用者可以自己適當的調整畫面位置。
  • 在該 activity 設 android:windowSoftInputMode ="adjustPan|adjustResize",讓系統幫忙處理。


android:windowSoftInputMode ="adjustPan"
  • Can prevent your background from resizing.
  • 不會呼叫 View.onSizeChanged()。
  • 不會調整 layout 所以不能保證能看到整個 layout 但會保持必能看到輸入框(平移)。
  • 設為 fullscreen 有時會使此參數失效,所以若是用 webview fullscreen 得注意。

android:windowSoftInputMode ="adjustResize"
  • 把原本的 layout(include background!) 往上頂,移出空間給 IME,但僅發生在 application 有可調整的空間。
  • 沒加此的話,不會一開啟就 focus on editText(?);加的話,一開啟就會 focus on 且有 soft input(?。
  • 會呼叫 View.onSizeChanged()。
  • 設為 fullscreen 有時會使此參數失效,所以若是用 webview fullscreen 得注意。


* Reference
- android:windowSoftInputMode
- Android Development Tips: Resizing layout while on-screen keyboard is displayed
- Issue 5497: adjustResize windowSoftInputMode breaks when activity is fullscreen
- Android windowSoftInputMode – Resize the application for the soft-keyboard
- Android: Soft Keyboard resizes background image
- android软键盘弹出引起的各种不适终极解决方案
- Android软键盘的隐藏显示研究 ***
- 关于android的输入法弹出来 覆盖输入框的问题
- Issue 14596: adjustPan not working correctly in landscape mode

2012年5月13日 星期日

[Android] The way to parser xml - SAX

Parser XML 可以用以下 API 達成:
  • SAX
  • Digester


SAX 
  • Simple API for XML。
  • 實作方式:
    • extends DefaultHandler
    • new SAXParserFactory
      • SAXParserFactory sAXParserFactory  =  SAXParserFactory.newInstance();
    • new SAXParser:
      • SAXParser sAXParser = sAXParserFactory.newSAXParser();
    • 從 SAXParser 中得到一個 XMLReader 的實例:
      • XMLReader xMLReader = sAXParser.getXMLReader();
    • Set Handler 到 XMLReader
      • xMLReader.setContentHandler(rssParser);
    • 藉 InputStream 取得 XML,用 handler 進行 parser。
      • xMLReader.parse(is);


DefaultHandler 執行方式:
  • startDocument()
    • 適合建立儲存物的集合 (ex: list)。
  • startElement(String namespaceURI, String localName, String qName, Attributes atts)
    • 解析過程中,遇到 XML 中的 tag 時,此 method 會被呼叫,可以由 localName 得知解析到那個 element 了。
    • 可以適當的建立相對物件。
    • attributes.getValue(NAME)
  • characters(char ch[], int start, int length)
    • 在執行 startElement() 後,此 method 會被呼叫,参数 ch[] 就是 element 中所帶的内容。
  • endElement(String namespaceURI, String localName, String qName)
  • endDocument()


* Reference
- android解析xml文件的方式(其二) - 东子哥 - 博客园
- 使用SAXParser取得XML文件里的属性值 - XML - AJava
- Android RSS解析步骤 | 易网联信
- SAX之:SAXParserFactory与SAXParser - 小文字 - 博客园

2012年5月6日 星期日

[Spring] configurations


<!-- Activates various annotations to be detected in bean classes -->
<!-- 設定註釋注册到Spring容器 -->
<context:annotation-config />

<!-- Scans the classpath for annotated components that will be auto-registered as Spring beans.
 For example @Controller and @Service. Make sure to set the correct base-package-->
<!-- 在 base-package下尋找有 @Component 和 @Configuration 的 target Class予註冊為 bean -->
<context:component-scan base-package="org.krams.tutorial" />

<!-- Configures the annotation-driven Spring MVC Controller programming model.
Note that, with Spring 3.0, this tag works in Servlet MVC only!  -->
<mvc:annotation-driven />


* Reference
- krams::: Spring 3 MVC: Using @ModelAttribute in Your JSPs

2012年5月5日 星期六

[AndroidLayout] declare-styleable and TypedArray

自定 View,且定訂屬性可以使用在 layout xml 中並取得其值。
  • Define attributes in <declare-styleable>。
  • extends View,畫出自己的圖,也可取得 xml 中的設定值。
  • 可在 layout xml 中引用自訂的 View。


Define attributes in <declare-styleable>。
  
      
          
          
      
  

extends View,畫出自己的圖,也可取得 xml 中的設定值。
public class CustomView extends View {
    private Paint paint;

    public CustomView(Context context,AttributeSet attrs) {  
        super(context,attrs);  
        paint = new Paint();  
          
        // 取出自定的 attributes from MyView.
        TypedArray a = context.obtainStyledAttributes(attrs,  
                R.styleable.MyView);  

        // 個別取出 attribute,要給預設值,以在 xml 中沒有定義時使用。  
        int textColor = a.getColor(R.styleable.MyView_textColor,  
                Color.WHITE);  
        float textSize = a.getDimension(R.styleable.MyView_textSize, 36);  
          
        paint.setTextSize(textSize);  
        paint.setColor(textColor);  
        
        // Give back a previously retrieved StyledAttributes, for later re-use.
        a.recycle();  
    }  
}

可在 layout xml 中引用自訂的 View。
  
  

* Reference
- Android 中自定义控件和属性(attr.xml,declare-styleable,TypedArray)的方法和使用 - jincf2011的专栏 - 博客频道 - CSDN.NET
- Declaring a custom android UI element using XML
- public void recycle ()

2012年5月2日 星期三

[Publish] Filters on Google Play

  • Google Play 會 filter app 是否相容於 device 來決定是否顯示於 user,filter 主要條件是:
    • 以宣告在 AndroidManifest.xml 中的 設定來和 device's configuration 做比對。
    • User's country and carrier, the presence or absence of a SIM card, and other factors. 
    • Filter 是以版本為根本,假設 user 已安裝 v1,但 v2 不適用於他的 device 那麼 user 便不會收到此 app 的更新通知。

Based
  • <supports-screens>
    • Smaller layout can be used on Larger screens; but Larger screen cannot be used on Smaller screens.
    • ex: Only declares: normalScreen
      • Available to both normal- and large-screen devices.
      • Not available to small-screen devices.
  • <uses-configuration>
    • Device Configuration: keyboard, navigation, touch screen
  • <uses-feature>
    • This functionality was introduced in Android 2.0 (API Level 5).
    • Device Features from name, ex:
      • <uses-feature android:name="android.hardware.sensor.light" />
    • OpenGL-ES Version(openGlEsVersion), ex:
      • <uses-feature android:openGlEsVersion="int">
    • 即使有些 device features 開發者並沒有宣告在此,Google Play 也會藉由<uses-permission>推出些 app 中應該會用到的 features 來做為 filter 條件。
  • <uses-library>
    • Device 中應該要有的 shared library。
  • <uses-permission>
    • 事實上並沒有直接使用宣告於此的做為 filter 條件,但會從此推論出應該使用到的 device feaures。
  • <uses-sdk> 
    • Minimum Framework Version (minSdkVersion) 
      • <uses-sdk android:minSdkVersion="3">
    • Maximum Framework Version (maxSdkVersion)
      • <uses-sdk android:maxSdkVersion ="10"> 
      • Deprecated. Android 2.1 以上(含)已不會再檢查此 attribute
      • The SDK will not compile ifmaxSdkVersion is set in an app's manifest. For devices already compiled with maxSdkVersion, Google Play will respect it and use it for filtering.
      • 不建議宣告此 attribute。


Advanced manifest filters
以下 attributes 通常使用於 high-performance games and similar applications that require strict controls on application distribution. Most applications should never use these filters.
  • <compatible-screens>
    • Google Play filters the application if the device screen size and density does not match any of the screen configurations (declared by a <screen> element) in the <compatible-screens>element.
    • Normally, you should not use this manifest element. Using this element can dramatically reduce the potential user base for your application, by excluding all combinations of screen size and density that you have not listed. 
  • <supports-gl-texture>


Other Filters
  • Application and publishing characteristics that affect filtering on Google Play.
  • Publishing Status
    • Only published applications will appear in searches and browsing within Google Play.
  • Priced Status
    • Not all users can see paid apps. 
    • To show paid apps, a device must have a SIM card and be running Android 1.1 or later, and it must be in a country (as determined by SIM carrier) in which paid apps are available.
  • Country / Carrier Targeting
  • Native Platform
  • Copy-Protected Applications

How Google Play filters by features

Google Play compares:
  • Features required by the application
    • An application declares features in <uses-feature> elements in its manifest 
  • Features available on the device, in hardware or software
    • A device reports the features it supports as read-only system properties.
    • 當 user 開啟 Google Play 會呼叫 PackagManager.getSystemAvailableFeatures() 取得 device features. 


How Google Play handles app
每次 developer 上傳 app 時,會列出 AndroidManfest.xml 中會用來做為條件的內容。
這些所得的 list 會做為 apk 的 metadata 與 the application .apk and the application version 儲存一起.
  • Filtering based on explicitly declared features
    • <uses-feature> 中  anandroid:required=["true" | "false"] attribute (API level 5 or higher),預設為 true,表示一定要符合。
    • 所以若不想因為此 feature 而被 filter 掉,可宣告此 feature 並將此參數設為 false。 
  • Filtering based on implicit features
    • 有可能因為下列因素 app 中有使用到某些 features 但並未被宣告
    • Compiled Android Library
      • Android 1.5  前並未有 <uses-feature> element.
      • The developer 誤以為所有裝置都會有此 feature 因此沒有宣告。
      • The developer 忘了.
      • The developer declared the feature explicitly, but the declaration was not valid. 
        • For example, 拼錯 feature 名稱。
    • 所以..
      • Google Play 會利用 <uses-permission> 去推論會使用到的 features 並自行做為 filter 條件。
      • 但如果不想要這樣則必須明確宣告在 <uses-feature> element 並且設 android:required="false"。


Special handling for Bluetooth feature
  • Google Play enables filtering for the Bluetooth feature only if the application declares its lowest or targeted platform as Android 2.0 (API level 5) or higher
  • However, note that Google Play applies the normal rules for filtering when the application explicitly declares the Bluetooth feature in a <uses-feature> element.


執行下列 command 可預知 Google Play 所得的 filter 條件

Android Tools > Export Unsigned/signed Application Package

# aapt dump badging <path_to_exported_.apk>


* Reference
- Filters on Google Play
<uses-feature>

[UI] Supports Multiple Screen - Scaling

If layout is dependency on pixel...
  • mdpi -> ldpi: 圖會變大而失真
  • mdpi -> hdpi: 圖會變小 (因為 pixel 變多/ inch)
  • 也因此在 ldpi mdpi hdpi 上會顯得大小不一

但若是採用 independency methods...
  • 則系統會選擇不同的 resource 所以如果只有 mdpi:
    • 則會縮小顯示在 ldpi device 上
    • 則會放大顯示在 hdpi device 上 而可能失真
  • 最終在 ldpi mdpi hdpi 大小會相同

Multiple screens support
  • Started in Android 1.1
  • Resources management added in 1.5
  • Compatibility mode added in 1.6

Inside Android
  • Everything is pixels
  • Resolution independent units
    • dip and dp
    • pt and sp
    • mm, in
  • Layouts

Resources management
  • Pre-scaling
  • Auto-scaling
  • By default, resources are mdpi
    • res/drawable
  • Use dpi-specific resources
    • res/drawable-hdpi
    • res/drawable-ldpi
    • res/drawable-mdpi


Pre-scaling (android:anydensity="true")
  • 系統善用 resources 的方式。系統會根據裝置 density 去選擇要使用那種大小的圖片(res/drawable-ldpi, drawable-mdpi, drawable-hdpi...)或者是放大/縮小 default drawable 來符合當下螢幕密度。
  • 如果 application 中沒有相符合的 resources 那麼系統就會使用預設的(res/drawable or res/drawablw-mdpi)並且放大或縮小它來顯示。
    • res/drawable 被視為 baseline screen density (mdpi)。
  • 如果取得已被放大/縮小的圖片的 dimension,那麼值會是已經放大/縮小後的。
  • Examples:
    • for an hdpi device, when there is only mdpi image 100 x 100, then the image will be pre-scaled to 150 x 150;
    • for an mdpi device, when there is only hdpi image 150 x 150, then the image will be pre-scaled to 100 x 100;
  • 此功能預設是 true,如果不想讓圖片被經過這樣的處理或是放大/縮小後顯示,可...
    • 將 resources 放在 res/drawable-nodpi 下。
    • 在 AndroidManifest 中設 <supports-screens android:anydensity="false">。
    • 設定 Bitmap 的 isScaled() 為 false。
    • 當 pre-scaling 被關閉,系統便會在畫圖時縮放圖片(see Auto-scaling),但不建議關閉 pre-scaling。

Auto-Scaling
  • 若想強迫使用 auto-scaling,則是要關閉 pre-scaling,ex: 在 AndroidManifest 中設 <supports-screens android:anydensity="false">。
  • 為了確保在不同裝置上能顯示相同的大小,所以即使 pre-scaling is disable 仍會再畫圖時做 auto-scaling。
  • CPU expensive, but use less memory.
  • Bitmap created at runtime will auto-scaled.


AndroidManifest.xml
  • android:anyDensity: 程序是否可在任何密度的螢幕上執行。主要是為使用了 px 作為單位的圖片。
    • If false: 系統就會 pre-scaling resources/density-compability,根據不同的屏幕密度將 px 值轉換為合理的大小。
    • If true: 就會關閉 pre-scaling resources/density-compability 。
    • 如果程序是以 dp 作為長度單位的,則不會受此值影響。
  • android:xxxScreens: 是否支持某屏幕(physical size)。
    • If false: 表示不支援該大小的螢幕,系統會啟用 size-compability 特性,即只顯示標準屏幕(normal size, mdpi)的大小。
      • ex: 即使是 hdpi 仍以 mdpi 的大小顯示,其餘部份則會留黑。
    • If true: 表示支援該大小的螢幕,系統就不會做任何處理直接顯示。

可以利用下列兩種方式來在程式中相對的長度:

計算出 dipValue 在該螢幕中應該為的 pixel value。
// Convert the dips to pixels
final float scale = getContext().getResources().getDisplayMetrics
().density;
pixels = ( int) (dipValue * scale + 0.5f );
宣告 dip 在 resources values 中,再取出該 pixel size by getDimensionPixelSize()

    20dip 

Resources r = aContext.getResources();
int length = r.getDimensionPixelSize(R.dimen.length);


* Reference
- 2009_Android_resolution_independence_and_high_performance_graphics_RomainGuy ***
Supporting Multiple Screens
- Situee's Blog - iPhone,Technology: Pre-scaling, Auto-Scaling and Screen Density
- How to Support Multiple Screens in Android without the need to Provide different bitmap drawables for different screen densities
- Android Samsung S I9000 screen size and density issues
- Android 屏幕兼容性
- Android ApiDemos示例解析(63):Graphics->Density (上)  ***
- Android ApiDemos示例解析(63):Graphics->Density (下)  ***
- android应用 DPI不同的适配问题分析 **

2012年5月1日 星期二

[AndroidGraphic] Canvas and Drawables

Drawing 2D graphics:
  • 由 layout 來畫。適用於不是太複雜、不需動態更動、像遊戲需要要求效率的圖 。
  • 直接用 Canvas 來畫出你的圖。適用於會規律性更新內容的圖。
    • You personally call the appropriate class's onDraw() method (passing it your Canvas), or one of the Canvas draw...() methods (like drawPicture()).
    • Doing in which thread:
      • In UI thread: call invalidate() and then handle the onDraw() callback.
      • In a separate thread: wherein you manage a SurfaceView and perform draws to the Canvas as fast as your thread is capable (you do not need to request invalidate()).

Draw with a Canvas
  • A Canvas works for you as a pretense, or interface, to the actual surface upon which your graphics will be drawn — it holds all of your "draw" calls. 
  • 有兩種使用方式
    • On a View (extends View)
      • Using within the onDraw() callback method, the Canvas is provided for you and you need only place your drawing calls upon it. 
    • On a SurfaceView
      • You can also acquire a Canvas from SurfaceHolder.lockCanvas(), when dealing with a SurfaceView object.
  • If you need to create a new Canvas, then you must define the Bitmap upon which drawing will actually be performed. 
  • The Bitmap is always required for a Canvas.
  • You can set up a new Canvas like this:
// 在此 Canvas 上所畫的內容,會以傳入的 Bitmap 為底。
Bitmap b = Bitmap.createBitmap(100,100,Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);

// 然後可以藉由 Canvas.drawBitmap() 得到所畫的 Bitmap。
// Drawable has its own draw() method that takes your Canvas as an argument.
drawable.draw(canvas); // 將 drawable 畫到 canvas 上。
It's recommended that you ultimately draw your final graphics through a Canvas offered to you by View.onDraw() or SurfaceHolder.lockCanvas().


On a View
如果 view 中沒有含大量處理過程或是會一直更新畫面(frame-rate speed, ex: chess game, a snake game, or another slowly-animated application),那麼可以繼承 View 客制自己的 view,在 View.onDraw() 中利用 Android Framework 傳入的 Canvas 畫圖。
  • 當要畫出你的 View 時,Android Framework 會呼叫 View.onDraw() ,但 The Android framework 只會在需要時去呼叫 onDraw(),不過你也可以藉 invalidate() 去觸發此呼叫,你的 view 會被重繪。
  • invalidate() 只能在 UI/main thread 中被呼叫,若是要在 non-UI thread 中呼叫,改使用 postInvalidate().


On a SurfaceView (android.view.SurfaceView)
  • The SurfaceView is a special subclass of View that offers a dedicated drawing surface within the View hierarchy.
  • 可以控制它的格式和大小。
  • SurfaceView 會負責把它的 surface 放在螢幕上正確的位置。
Purpose:
  • 在 View hierarchy 還沒準備好前,便可以在 secondary thread 中利用 SurfaceView 和它的 Canvas 繪畫且在 secondary thread rendering 它到 screen。
    • To offer this drawing surface to an application's secondary thread, so that the application isn't required to wait until the system's View hierarchy is ready to draw.
    • To provide a surface in which a secondary thread can render into the screen. 
  • Instead, a secondary thread that has reference to a SurfaceView can draw to its own Canvas at its own pace.
Process:
  • 藉 SurfaceHolder interface 的 getHolder() 可以取得和它相關的 surface。
  • 當 SurfaceView's window 為可視時,Surface 會被建立。
  • Implement surfaceCreated(SurfaceHolder) and surfaceDestroyed(SurfaceHolder) 就可以看到當 window 顯示與隱藏時,Surface 也被建立與摧毀。
To be aware of some threading semantics:
  • All SurfaceView and SurfaceHolder.Callback methods will be called from the thread running the SurfaceView's window (typically the main thread of the application).
    • They thus need to correctly synchronize with any state that is also touched by the drawing thread.
  • You must ensure that the drawing thread only touches the underlying Surface while it is valid -- between SurfaceHolder.Callback.surfaceCreated() and SurfaceHolder.Callback.surfaceDestroyed().

How to use?
  • Create a new class that extends SurfaceView.
  • The class should also implement SurfaceHolder.Callback.
  • This subclass is an interface that will notify you with information about the underlying Surface, such as when it is created, changed, or destroyed.
  • Inside your SurfaceView class is also a good place to define your secondary Thread class, which will perform all the drawing procedures to your Canvas.

Note:
  • Instead of handling the Surface object directly, you should handle it via a SurfaceHolder.
  • When your SurfaceView is initialized, get the SurfaceHolder by calling getHolder().
  • Notify the SurfaceHolder that you'd like to receive SurfaceHolder callbacks (from SurfaceHolder.Callback) by calling addCallback() (pass it this).
  • Override each of the SurfaceHolder.Callback methods inside your SurfaceView class.
  • On each pass you retrieve the Canvas from the SurfaceHolder, the previous state of the Canvas will be retained. In order to properly animate your graphics, you must re-paint the entire surface. 
    • For example, you can clear the previous state of the Canvas by filling in a color with drawColor() or setting a background image with drawBitmap(). Otherwise, you will see traces of the drawings you previously performed.


Drawables
  • A Drawable is a general abstraction for "something that can be drawn."
  • In application, 一個 drawable 只會擁有一份,狀態是共享,因此不管怎麼取得擁有,修改了其中的狀態,則原圖(其他 instance) 也會改變。
    • Each unique resource in your project can maintain only one state, no matter how many different objects you may instantiate for it. 
    • For example, if you instantiate two Drawable objects from the same image resource, then change a property (such as the alpha) for one of the Drawables, then it will also affect the other. So when dealing with multiple instances of an image resource, instead of directly transforming the Drawable, you should perform a tween animation.
  • 可以使用 mutate() 取得原圖,這樣這個就不會被改變到。

There are three ways to define and instantiate a Drawable:
  • Using an image saved in your project resources;
    • Supported file types are PNG (preferred), JPG (acceptable) and GIF (discouraged).
    • 放在 res/drawable/ 下的圖片,在 build 的過程,aapt 會自動以失真最少的方式壓縮圖片簡省空間。
    • 若是圖片不想被壓縮則可以放在 res/raw/ 下。
  • Using an XML file that defines the Drawable properties;
    • This philosophy caries over from Views to Drawables. 
    • If there is a Drawable object that you'd like to create, which is not initially dependent on variables defined by your application code or user interaction, then defining the Drawable in XML is a good option. 
    • Even if you expect your Drawable to change its properties during the user's experience with your application, you should consider defining the object in XML, as you can always modify properties once it is instantiated.
    • Any Drawable subclass that supports the inflate() method can be defined in XML and instantiated by your application.
  • Using the normal class constructors.


Shape Drawable
  • When you want to dynamically draw some two-dimensional graphics, a ShapeDrawable object will probably suit your needs.
  • With a ShapeDrawable, you can programmatically draw primitive shapes and style them in any way imaginable.


* Reference
- Canvas and Drawables | Android Developers

2012年4月28日 星期六

[UI] Supporting Multiple Screens - Terms and Concepts

* Terms and Concepts
  • Screen size (inch)
    • 以螢幕對角線為準,可分為small, normal, large, and extra large。
  • Aspect ratio
    • 螢幕的長寬比。
  • Resolution 解析度
    • The total number of physical pixels on a screen.
  • Density
    • pixel 密度 (the spread of pixels across the physical width and height of the screen)。
    • 可分為 low, medium, large, and extra large。
  • Density-independent pixel (dp)
    • A virtual pixel unit that applications can use in defining their UI, to express layout dimensions or position in a density-independent way。
    • pixels = dps * (density / 160)。
  • px (pixels)
    • 像素,對電腦而言,所有人眼所見的影像都是螢幕上一連串的光點的構成的,這些光點是電腦顯示的最小單位。
    • 光點的數量越多,影像提供的細節就越多。

* Range of screens supported
At run time, the platform handles the loading of the correct size or density resources, based on the generalized size or density of the current device screen, and adapts them to the actual pixel map of the screen.
  • Sizes
    • small, normal, large, and xlarge
  • Densities
    • ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high)
    • The xhdpi density category was added in Android 2.2 (API Level 8). 
    • The xlarge size category was added in Android 2.3 (API Level 9).

* Android support application to display resources
  • Pre-scaling of resources (such as image assets)
  • Auto-scaling of pixel dimensions and coordinates
  • Compatibility-mode display on larger screen-sizes

* 若要指定特定長度或大小,要使用以下單位,才不會因為系統的 resolution 不同而呈現不同結果:
  • sp (scaled pixels): 用於字體。
  • dip/dp (density independent pixels): 系統會依比例呈現,使得結果不受 pixel 影響。


* Reference
- Supporting Multiple Screens
- long or notlong
- 關於android系統資源更換-語言切換或配置改變
- 屏幕分辨率
- 关于android多分辨率中的density和density-independent pixel的区别
- 何謂解析度、DPI?
- android平台下单位px,dip,sp的区别

[AndroidGraphic] Bitmap and Drawable

// drawable 轉換為 bitmap: 利用canvas物件來達成。
Bitmap drawableToBitmap(Drawable drawable) { 
    Bitmap.Config c = drawable.getOpacity() != PixelFormat.OPAQUE ? 
        Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
    Bitmap bitmap = Bitmap.createBitmap( 
        drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), c);
    Canvas canvas = new Canvas(bitmap); 
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), 
    drawable.getIntrinsicHeight()); 
    drawable.draw(canvas); 
    return bitmap;
}

Bitmap bitmap = ((BitmapDrawable) iconDrawable).getBitmap();
new BitmapDrawable(Bitmap.createScaledBitmap(bitmap, 128, 128, true))


// bitmap 轉換為 drawable: 利用BitmapDrawable直接轉換。
Drawable bitmapToDrawable(Bitmap bitmap) {
    Drawable drawable = new BitmapDrawable(bitmap);return drawable;
}


* Reference
- Camangi 市集 - 關發商資訊

[Multimedia] Video format

傳送方式
  • 交錯(隔行)掃瞄 (interlace, abbr: i)
    • 早年廣播技術不發達,頻寬甚低時用來改善畫質的方法。
    • 是一種將圖像顯示在掃描式的顯示設備上的方法。
    • 在同樣幀率的情況下,這種方法比起逐行掃描引起的視覺閃爍比較小。
    • ex: NTSC, PAL, SECAM, 陰極射線管(CRT for Cathode Ray Tube)。
  • 循序掃瞄 (Progressive, abbr: P)
    • 是一種在顯示設備表示運動圖像的方法,這種方法將每幀的所有像素同時顯示(逐行掃描有時候被稱為非隔行掃描)。
    • 每次畫面更新時都會刷新所有的掃瞄線。
    • 此法較消耗頻寬但是畫面的閃爍與扭曲則可以減少。
    • 為了將原本為交錯掃瞄的視訊格式(如DVD或類比電視廣播)轉換為循序掃瞄顯示設備(如LCD電視,電漿電視等)可以接受的格式,許多顯示設備或播放設備都具備有去交錯的程序。但是由於交錯信號本身特性的限制,去交錯並無法達到與原本就是循序掃瞄的畫面同等的品質。
    • 常被用在計算機顯示器上。通常的顯示器的掃描方法都是從左到右從上到下,每秒鐘掃描固定的幀數(稱為幀率,例如60幀每秒)。

色彩
  • 色彩空間(Color Space)或色彩模型(Color model name)規定了視訊當中色彩的描述方式。
  • ex: NTSC 電視使用了 YIQ 模型,而 PAL 使用了 YUV 模型,SECAM 使用了 YDbDr 模型。
  • 在數位視訊當中,像素資料量(bits per pixel,簡寫為 bpp)代表了每個像素當中可以顯示多少種不同顏色的能力。由於頻寬有限,所以設計者經常藉由色度抽樣之類的技術來降低 bpp 的需求量。

H.263
  • 由 ITU-T 制定的視頻會議用的低碼率視頻編碼標準,屬於視頻編解碼器。
  • 最初設計為基於 H.324 的系統進行傳輸(即基於公共交換電話網和其它基於電路交換的網路進行視頻會議和視頻電話)。
  • 下一代視頻編解碼器是 H.264,或者叫 AVC 以及 MPEG-4 第10部分。由於 H.264 在性能上超越了 H.263 很多,現在通常認為 H.263 是一個過時的標準。

H.264/MPEG-4 AVC
  • 是由 ITU-T 視頻編碼專家組(VCEG)和 ISO/IEC 動態圖像專家組(MPEG)聯合組成的聯合視頻組(JVT,Joint Video Team)提出的高度壓縮數字視頻編解碼器標準。
  • JVT 編解碼器 (由於該標準是由 JVT 組織並開發的)
  • ITU-T 的 H.264 標準和 ISO/IEC MPEG-4第10部分(正式名稱是ISO/IEC 14496-10)在編解碼技術上是相同的,這種編解碼技術也被稱為 AVC(進階視訊編碼, Advanced Video Coding。
  • 標準第一版的最終草案已於2003年5月完成。
  • 此標準有以下稱呼來明確的說明它兩方面的開發者:
    • H.264/AVC
    • AVC/H.264
    • H.264/MPEG-4 AVC
    • MPEG-4/H.264 AVC

MPEG (通常指MPEG-1)
  • Moving Picture Experts Group。
  • 本來的含義是指一個研究視頻和音頻編碼標準的「動態圖像專家組」組織,成立於1988年,致力開發視頻、音頻的壓縮編碼技術,至今已經制定了MPEG-1、MPEG-2、MPEG-3、MPEG-4、MPEG-7等多個標準,。
  • 現在我們所說的 MPEG 泛指由該小組制定的一系列視頻編碼標準。
  • 是基於變換的有損壓縮。光學信號線經過採樣形成視頻信號,視頻信號基本的單位叫做影格,一個影格就是一個獨立的圖像,然後影格被分割成小塊做變換編碼,然後量化,最後進行熵編碼。
  • 與傳統影像編碼技術不同,MPEG 並不是每格影像進行壓縮,而是以一秒時段作為單位,將時段內的每一格影像做比較,由於一般視頻內容都是背景變化小、主體變化大,MPEG 技術就應用這個特點,以一幅影像為主圖,其餘影像格只記錄參考資料及變化數據,更有效記錄動態影像。從MPEG-1到MPEG-4,其核心技術仍然離不開這個原理,之間的分別主要在於比較的過程和分析的複雜性等。
  • MPEG 只規定位元流的格式與解碼精確度(即規定解碼的方法),而任何人可依照MPEG標準以不同方式實現編碼器(程式)。
  • 除了可減少因編碼專利造成的商業利益糾紛外,MPEG標準的主要目的在於確保不同的編碼器所產生的位元流可被其他解碼器正確的解碼,只要此位元流符合標準。

720p
  • 是一種視頻顯示格式。
  • 字母 p 意為逐行掃描(progressive scan),數字 720 則表示垂直方向有 720 條掃描線。
  • 通常畫面解析度為 1280 × 720,一般亦可稱為高畫質(HD)
  • 但有些情況下,如iPod Touch 4,其720P攝錄並不是指1280×720(16:9),而是960×720(4:3),故沒有註明是HD的720P攝錄並不是都指1280×720(16:9)。


新的高畫質電視(HDTV)解析度可達1920x1080p60,即每條水平掃瞄線有1920個像素,每個畫面有1080條掃瞄線,以每秒鐘60張畫面的速度播放。

* Reference
- 影片
- 隔行掃描
- 逐行掃描
- H.263
- MPEG
- H.264/MPEG-4 AVC
- JVT
- 720p
- 頗析 720p, 1080i 和 1080p

[Android] INSTALL_FAILED_CONFLICTING_PROVIDER

Error Message
[2010-02-28 04:14:38 - mobileFinder]Installation error: INSTALL_FAILED_CONFLICTING_PROVIDER
[2010-02-28 04:14:38 - mobileFinder]Please check logcat output for more details.
[2010-02-28 04:14:38 - mobileFinder]Launch canceled!


Solution
在安裝 apk 時,系統便會依 AndroidManifast.xml 中的宣告註冊

android:authorities 在系統中不可重覆。


* Reference
- Android: INSTALL_FAILED_CONFLICTING_PROVIDER « Hustle Play

[SQL] AND has more priority than OR

* Priority
  • In SQL: AND > OR
  • In Java: && > ||

SELECT count(*) FROM TABLE_A
    WHERE (X= 2 OR X = 5) AND Y = 0;
   
SELECT count(*) FROM TABLE_A
    WHERE X IN (2,5) AND Y = 0;


2012年4月21日 星期六

[AndroidNet] HTTP API

Android includes two HTTP clients: HttpURLConnection and Apache HTTP Client. Both support HTTPS, streaming uploads and downloads, configurable timeouts, IPv6 and connection pooling.

  • android.net.http.AndroidHttpClient - API 8 - 主要使用 Apache 的 HttpClient
    • Implementation of the Apache DefaultHttpClient that is configured with reasonable default settings and registered schemes for Android, and also lets the user add HttpRequestInterceptor classes. 
    • Don't create this directly, use the newInstance(String) factory method.

Their implementation is stable and they have few bugs. But Android Team is not actively working on Apache HTTP Client.


  • abstract java.net.URLConnection
    • Instances of URLConnection are not reusable: you must use a different instance for each connection to a resource.
    • An URLConnection for HTTP (RFC 2616) used to send and receive data over the web. Data may be of any type and length.
  • java.net.HttpURLConnection extends URLConnection
    • This class may be used to send and receive streaming data whose length is not known in advance.
    • Is a general-purpose, lightweight HTTP client suitable for most applications.
    • Prior to Froyo, HttpURLConnection had some frustrating bugs.
    • Work around this by disabling connection pooling (Refer:  Android’s HTTP Clients | Android Developers Blog)
    • In Gingerbread, we added transparent response compression.
    • In Ice Cream Sandwich, we are adding a response cache.

  • How to choose?
    • Eclair and Froyo  - Apache HTTP client that has fewer bugs.
    • For Gingerbread and better -  HttpURLConnection.
      • Its simple API and small size makes it great fit for Android.
      • Transparent compression and response caching reduce network use, improve speed and save battery.
      • Android Team will be spending our energy going forward.

* Reference
- Android’s HTTP Clients | Android Developers Blog
- Android 上的 HTTP 服務相關函式 (I)
- Android 上的 HTTP 服務相關函式 (II)
- Android 上的 HTTP 服務相關函式 (III)

2012年4月15日 星期日

[AndroidDev] Designing for Performance

  • Battery life is one reason you might want to optimize your app even if it already seems to run “fast enough”.
  • Choosing the right algorithms and data structures should always be your priority.
    • Using the right data structures and algorithms will make more difference than any of the advice here
  • Considering the performance consequences of your API decisions will make it easier to switch to better implementations later (this is more important for library code than for application code).
  • Different versions of the VM running on different processors running at different speeds.
  • There are also huge differences between devices with and without a JIT: the “best” code for a device with a JIT is not always the best code for a device without.

There are two basic rules for writing efficient code:
  • Don’t do work that you don’t need to do.
  • Don’t allocate memory if you can avoid it.


Avoid Creating Unnecessary Objects *
過多物件會占據太多空間,觸使系統 GC 的頻率變高,而在 GC 時會使得使用者在操作中感覺頓頓的,因為系統會暫停(lock)所有東西。
  • Fewer objects created mean less-frequent garbage collection, which has a direct impact on user experience.
  • If you allocate objects in a user interface loop, you will force a periodic garbage collection, creating little “hiccups” in the user experience.
  • 改善範例: 
    • 如果回傳的字串會再 append 到 StringBuffer,那麼可以直接傳入 StringBuffer 去 append 字串。
    • When extracting strings from a set of input data, try to return a substring of the original data, instead of creating a copy. You will create a new String object, but it will share the char[] with the data. (The trade-off being that if you’re only using a small part of the original input, you’ll be keeping it all around in memory anyway if you go this route.)
    • 使用一維矩陣取代多維矩陣;使用 primitive types array instead of Object type array. 
      • But this also generalizes to the fact that two parallel arrays of ints are also a lot more efficient than an array of (int,int) objects.
      • But tuples of two-dimension objects is usually better to trade good API design for a small hit in speed. 

Performance Myths
  • On devices without a JIT
    • 型別有指定特定的 type 會比使用 interface 有效率。For example, it was cheaper to invoke methods on a HashMap map than a Map map, even though in both cases the map was a HashMap
    • Caching field accesses is about 20% faster than repeatedly accesssing the field. 
  • With a JIT, field access costs about the same as local access, so this isn’t a worthwhile optimization unless you feel it makes your code easier to read. (This is true of final, static, and static final fields too.)

Prefer Static Over Virtual
If you don’t need to access an object’s fields, make your method static.

Avoid Internal Getters/Setters
  • Virtual method calls are expensive, much more so than instance field lookups.
  • It’s reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

Use Static Final For Constants
This optimization only applies to primitive types and String constants, not arbitrary reference types. Still, it’s good practice to declare constants static final whenever possible.
// Compiler 會產生  method(a class initializer method),在第一次使用這個 class 時會被執行。
// The method stores the value 42 into intVal, and extracts a reference from the classfile string constant table for strVal.
// When these values are referenced later on, they are accessed with field lookups.
static int intVal = 42;
static String strVal = "Hello, world!";
We can improve matters with the “final” keyword:
// 不會產生  method,因為常數會存在於 dex file 的 static field initializers。
// Code that refers to intVal will use the integer value 42 directly, and accesses to strVal will use a relatively inexpensive “string constant” instruction instead of a field lookup. 
static final int intVal = 42;
static final String strVal = "Hello, world!";

Use Enhanced For Loop Syntax (i.e for-each loop)
  • The enhanced for loop can be used for collections that implement the Iterable interface and for arrays.
  • 只要是 Collection 介面的實作物件,都可以用 foreach 語法,新增於 J2SE 5.0 之後。
// 如果走訪的是陣列,編譯器會自動展開為以下的程式碼:
public void go(int ai[]) {
    int ai1[] = ai;
    int i = ai1.length;
    for (int j = 0; j < i; j++) {
        int k = ai1[j];
        System.out.println(k);
    }
}

// 若是 Collection 的實作物件,其實編譯器會展開為:
public void go(Collection collection) {
    String s;
    for (Iterator iterator = collection.iterator(); 
        iterator.hasNext(); System.out.println(s))
        s = (String)iterator.next();
}

// 無論是 Collection、List 或 Set,展開後皆利用 iterator() 方法傳回 Iterator 物件,
// 並利用 Iterator 來移動、傳回下一個物件,這是 Iterator 模式 的實現。
// 所以其實在 for-each 中會多產生個 Iterator 物件,因此可寫成以下程式。
public void go(Collection collection) {
    if (collection.size() > 0)
        for(String element : collection) {
            System.out.println(element);
        }
}
To summarize:
  • Collections 使用 for-each loop; ArrayList 使用 for loop(?)。
    • Use the enhanced for loop by default, but consider a hand-written counted loop for performance-critical ArrayList iteration.
    • With an ArrayList, a hand-written counted loop is about 3x faster (with or without JIT), but for other collections the enhanced for loop syntax will be exactly equivalent to explicit iterator usage.

Consider Package Instead of Private Access with Private Inner Classes
Inner class 使用 Package(default) modifier,而不要使用 Private。
public class Foo {
    private class Inner {
        void stuff() {
            Foo.this.doStuff(Foo.this.mValue);
        }
    }

    private int mValue;

    public void run() {
        Inner in = new Inner();
        mValue = 27;
        in.stuff();
    }

    private void doStuff(int value) {
        System.out.println("Value is " + value);
    }
}

因為 VM 會認為從 Foo$Inner 直接去存取 Foo 的 private member 是不合法的(Foo and Foo$Inner are different classes),因此 compiler 會產生下列 methods(Accessors),也就是 Foo$Inner 事實上是透過這些 methods 來存取 Foo 中的 private members。
// package
static int Foo.access$100(Foo foo) {
    return foo.mValue;
}
// package
static void Foo.access$200(Foo foo, int value) {
    foo.doStuff(value);
}
Accessors are slower than direct field accesses! 所以將 inner class 宣告為 Package,但這樣也表示此 inner class 可以直被同個 package 下的 classes 存取,因此不可使用在 public API.

Use Floating-Point Judiciously
避免使用 float type。

Know And Use The Libraries

Use Native Methods Judiciously
  • Native code isn’t necessarily more efficient than Java. For one thing, there’s a cost associated with the Java-native transition, and the JIT can’t optimize across these boundaries.
  • Native code is primarily useful when you have an existing native code base that you want to port to Android, not for “speeding up” parts of a Java app.

Closing Notes
  • One last thing: always measure
  • Before you start optimizing, make sure you have a problem. Make sure you can accurately measure your existing performance, or you won’t be able to measure the benefit of the alternatives you try.


* Reference
- Designing for Performance
- 繼承
- Android App開發效能你知多少?
- Dalvik 記憶體管理
- Just-in-time compilation
- 初探JIT compiler 與 Android Dalvik VM
- Profiling with Traceview and dmtracedump
- Java Gossip: autoboxing、 unboxing
- Java Essence: 神奇的 foreach