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

2013年3月26日 星期二

[Android] Directory path for APIs


  • getFilesDir = /data/data/{package name}/files
  • getDatabasePath = /data/data/{package name}/databases/{database name}.db
  • // 私人的檔案,當移除 APP,此路徑下的也都會移除。
  • getExternalFilesDir = /mnt/sdcard/Android/data/{package name}/files/{file}
  • getDownloadCacheDirectory = /cache
  • getDataDirectory = /data
  • // 與應用程式的關聯直接分開的,當移除 APP,此路徑下的也不會被移除。
  • getExternalStorageDirectory = /mnt/sdcard 
  • getExternalStoragePublicDirectory = /mnt/sdcard/pub_test

2012年12月1日 星期六

2012年10月21日 星期日

[Android] Avoid Memory leak

  • 當記憶體不足,system 就必須暫停你的 application,執行 garbage collection,通常暫停的時間很短暫讓 user 感覺不到,但若是在移動 scroll 或是遊戲戰鬥中,可以感覺到效能和回應的下降。
  • "leak" meaning you keep a reference to it thus preventing the GC from collecting it.
  • 在 Android 中,一個 Process 只能使用 16M 記憶體(模擬器為 8M?),若是超過變會引發 Out-of-Memory exception(OOM)。


容易占據大量記憶體的行為:
  • view layout
  • drawing method of a view
  • the logic code of a game


Context Leak
keeping a long-lived reference to a Context.

Context 最常用來載入和存取資源,在 app 中一般會有 Activity and Application 兩種 Context
  • setContentView(new TextView(this));
  • 表示 the entire View hierarchy and all its resources reference 到這個 activity,有可能會使得此 Context leak。

可用以下兩種方式避免 Context leak:
  • 不要將 Context 使用在自己的 scope 之外。
  • 使用 Application context。
    • This context will live as long as your application is alive and does not depend on the activities life cycle. 
    • If you plan on keeping long-lived objects that need a context, remember the application object. You can obtain it easily by calling Context.getApplicationContext() orActivity.getApplication().

In summary, to avoid context-related memory leaks, remember the following:
  • Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
  • Try using the context-application instead of a context-activity
  • Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. 
    • The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance
  • A garbage collector is not an insurance against memory leaks


Bitmap Leak
  • 避免 Bitmap Leak 就必須使用 recycle 機制,適時的將不需要顯示的 Bitmap 物件回收。
  • 但還有另一種狀況: 產生 Bitmap 的時候,明明還有許多記憶體,卻發生了 OOM。
    • 假設現在產生了一個 13MB 的 Int array 物件,在使用完之後立即 recycle,照理說會空出 13MB 的空間,這時候繼續產生一個 10MB 的 Int array 物件不會有任何問題,反而生成一個 4MB 的 Bitmap 卻跳出OOM。
  • 在 Android 中,一個進程的記憶體可以由 2 個部門組成:Java 使用記憶體,C使用記憶體
    • 這兩個記憶體的和必需小於 16 MB,不然就會出現 OOM。
    • 而分配給 Java 使用的記憶體,縱使這塊記憶體被釋放了,也還是只能給Java的使用,所以就算釋放 Java 佔用的佔用了一個大塊記憶體,C 能使用的記憶體 = 16M - Java 某一瞬間占用的最大記憶體。 
    • 而 Bitmap 的生成是路程經過過程 malloc 進行記憶體分配的,佔用的是 C 的記憶體,這個也就說明了,上面所說的的 4MB Bitmap無法生成的原因,因為在 13MB 被Java用過後,剩下 C 能用的只有 3M 了。

補救方式
  • 使用 BitmapFactory.decodeStream() 產生Bitmap。
    • 儘量不要使用 setImageBitmap,setImageResource 或 BitmapFactory.decodeResource 來設置一張大圖,因為這些函數在完成 decode 後,最終都是通過 java 層的 createBitmap 來完成的,需要消耗更多記憶體。
    • 因此,改用先通過 BitmapFactory.decodeStream 方法,創建出一個 bitmap,再將其設為 ImageView 的 source,decodeStream 最大的秘密在於其直接調用 JNI >> nativeDecodeAsset() 來完成 decode,
    • 無需再使用 java 層的 createBitmap,從而節省了 java 層的空間。
    • decodeStream 直接拿的圖片來讀取位元組碼了,不會根據機器的各種解析度來自動適應,使用了 decodeStream 之後,需要在 hdpi 和 mdpi,ldpi 中配置相應的圖片資源,否則在不同解析度機器上都是同樣大小(圖元點數量),顯示出來的大小就不對了。
  • 設定圖片的 Config 參數,可以跟有效減少載入的記憶體。
    • BitmapFactory.Options inSampleSize:值越大解析度越小,佔用memory也越小。
  • 在 onPause/onStop/onDestory 時, 將沒用到的 Bitmap release(用recyle())
BitmapFactory.Options opts = new BitmapFactory.Options();
// Options 只保存图片尺寸大小,不保存图片到内存
// 缩放的比例,缩放是很难按准备的比例进行缩放的,其值表明缩放的倍数
// SDK 中建议其值是2的指数值,值越大会导致图片不清晰
opts.inSampleSize = 4;
Bitmap bmp = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts);                              
 ...               
//回收
bmp.recycle();


* Reference
- Tracking Memory Allocations | Android Developers
- Avoiding memory leaks | Android Developers Blog
- (转)内存溢出的解决办法 Android - 攀升·Uranus - C++博客
- Android開發——解決載入大圖片時記憶體溢出的問題 @ 資訊園 :: 痞客邦 PIXNET ::
- GiveMePasS’s Android惡補筆記: 如何改善Bitmap所帶來的Out of Memory(OOM)問題
- Re: [問題] Bitmap OutOfMemory 永遠的痛 - 看板 AndroidDev - 批踢踢實業坊
- Andorid , Object-C and Java Programming Learning: [Android]Android Out Of Memory(OOM) 的詳細研究

2012年9月15日 星期六

[Android] Memory Cache

Reference
  • reference 的可以分為多種強度,我們最熟悉和最常使用的是 strong reference。
  • Four different degrees of reference strength: strong, soft, weak, and phantom.
  • 強度的差異在於 reference 和 garbage collector 間的互相影響關係。

Strong Reference
// buffer 就是 strong reference
StringBuffer buffer = new StringBuffer();
  • 當 reference 指向一個以上的物件,便是 strong reference。
  • 可以防止此 reference 被 GC。
  • 缺點:
    • Memory: 因為使得物件不能被回收,所以有造成 memory leak 的危險。
    • Caching: 假設在 application 中應用到許多大圖片,為了一直 reload 而 cache 圖片,所以 always 會有 reference 指向圖片,使得它在 memory 且不會被回收,也就是說我們得決定它是否該被移除且使其可以回收。

WeakReference
weak reference 則是隨時有可能已被回收。
// API 使用方式如下,建立 Widget 的 WeakReference。
WeakReference weakWidget = new WeakReference<widget>(widget);
// 取出 Widget object。
// 注意: 因為物件可以被回收,所以可能會得到 null。
weakWidget.get()
WeakHashMap
  • 作用類似 HashMap,只是 key 是使用 weak reference,若 key 變成 garbage 則它的 entry 便自動會被移除。
  • 但並不是你啥也也沒做他就能自動釋放,而是你使用到 value 才會被釋放。
  • super(key, queue); 只有 key 才是 weak reference,value 仍是 strong reference,所以 System.gc() 後,key 會被清除,value 則是才被視為 weak reference 然後到被調用到了才會被清除。

Reference queues
  • 當 WeakReference 回傳 null 時表示指向的物件已被回收,WeakReference object 也無用了,所以如 WeakHashMap 會去移除這類的 WeakReference object,避免 WeakHashMap 一直成長,其中卻有很多無用的 WeakReference 。
  • ReferenceQueue 可以幫助你管理這些 dead reference。
    • 如果你將 ReferenceQueue 傳入 weak reference's constructor,當有 reference 指向的物件被回收時,該 reference 會自動被 insert 到 ReferenceQueue 中,所以你可以定期清裡 ReferenceQueue 也就會清理了 dead reference。

Soft references
  • 類似於 weak reference,差異是比 weak reference 不易被回收。
  • 因為 soft reference 會盡量被保留在 memory 所以適合做 image cache。

Phantom References
  • Its get() method always returns null.
  • 用處:
    • 可以讓你決定何時將物件從 memory 移除。ex: manipulating large images,你可以先確定現在這一張已被移除,再載入下一張以避免 OOM。
    • 避免 finalize() method 可以 "resurrect" 建立了 strong reference 的 object。
      • override finalize() 的物件至少要被視為 GC 對象兩次以上才能被回收到,而不能及時的被回收,也因此會有多個待回收的 garbage 存在著等著被回收。

Android itself employs some caching as part of the resources infrastructure, so you are already getting the benefit of memory caching.

使用 bitmap 時,記得使用 recycle(),可以幫助釋放空間,所以若是再呼叫 getPixels() or setPixels(),可能會得到 exception,所以建議當不會再使用到 bitmap 時再使用。

LruCache
  • API level 12 (3.1)
  • Support Library back to API level 4 (1.6).
  • 管理與 cache 物件,呼叫 get(key) 取出物件,若物件不存在則會呼叫 create() 產生物件,並將新產生的物件加入 head of cache 再將其回傳。
  • 加入新物件時,cache 會檢查是否超過指定的大小,若超過則會刪除最後一筆 (tail of cache list)。

// override 這個 method 可以讓我們決定 cache 中每個物件 size 怎麼計算,default returns 1。
@Override
protected int sizeOf( String key, Bitmap value )
{
    return value.getByteCount();
}

Note:
Bitmap#getByteCount()
  • Supported from API Level 12。
// 建構子中則傳入想預設此 cache 的大小,這裡設定最大為 5 M。
// 所以一旦超過 5 M,物件會從最後一直被移除直到總大小小於 5 M。
public LruMemoryCache(Context context)
{
    super( 5 * 1024 * 1024 );
    this.context = context;
}

為避免發生 OutOfMemoryError,在系統呼叫 onLowMemory() 時建議呼叫 LruCache#evictAll() 移除所有元素再重建。

Note:
  • onLowMemory() 會被呼叫是因為整個系統的空間不足而不是因為你的 App 所用的空間已不足!
    • 所以等到此 method 被呼叫時已來不及,更好的方式是在 App 執行一開始便設定適當的大小限制給它。
    • ActivityManager#getMemoryClass() (API Level 5) 可以取得該 application 在 該 device 中的分配空間:
      • 單位為 megabytes。
      • 預設為 16 M,空間大點裝置可到 24 或更高。

也可以利用 LruCache 來管理在 SD card 中的檔案大小:
  • 儲存 File object 在 LruCache(override create())。
  • 以 file.length() 計算檔案大小 (override sizeOf())。
  • 移除物件時刪除 SD card 中的檔案 (override entryRemoved())。


* Reference
- Understanding Weak References | Java.net
- Styling Android » Blog Archive » Memory Cache – Part 1
- Styling Android » Blog Archive » Memory Cache – Part 2
- Styling Android » Blog Archive » Memory Cache – Part 3
- Styling Android » Blog Archive » Memory Cache – Part 4
- WeakHashMap的神话 - - ITeye技术网站
- WeakHashMap是如何清除不用的key的

2011年11月6日 星期日

[Android] Android Developer Tool (ADT) - Resources compilation

[Definition]
  • A plugin for Eclipse that provides a suite of tools that are integrated with the Eclipse IDE.
  • It can integrated Android project creation, building, packaging, installation, and debugging.
    • Add components based on the Android Framework API.
      • Java programming language and XML editors
      • Create an application UI.
    • SDK Tools integration
      • Debug your applications using the Android SDK tools.
    • Export signed (or unsigned) .apk files in order to distribute your application.

[ADT 14.0.0 (October 2011)]
  • Added webcam support to Android 4.0 or later platforms to emulate rear-facing cameras
  • Resource compilation
    • Changed how library projects are built in Eclipse.
      • You need SDK Tools r14 or newer to use the new library project feature that generates each library project into its own JAR file.
    • Improved incremental builds so that resource compilation runs less frequently.
    • Builds no longer run when you edit strings or layouts (unless you add a new id)
    • No longer run once for each library project.
    • No longer happens for normal save operations. It only happens when running or debugging (the build option that lets you disable the packaging step, which was introduced in ADT 12, is now on by default.)
  • Added the "Go to Matching" (Ctrl-Shift-P) feature, which lets you jump between opening and closing tags in XML files.

[Library project]
  • Source code in the library project can access its own resources through its R class.
  • Can reference other library projects and can import an external library (JAR) in the normal way.
  • Differs from an standard Android application project:
    • Cannot compile it directly to its own .apk and run it on an Android device.
    • Can not include raw assets.
    • Cannot export the library project to a self-contained JAR file, as you would do for a true library. (Changed in r14?)
      • Instead, you must compile the library indirectly, by referencing the library in the dependent application and building that application.
Usage
  • When you build an application that depends on a library project, the SDK tools compile the library into a temporary JAR file and uses it in the main project, then uses the result to generate the .apk. 
    • ADT creates virtual source folders linking to the library source folders.
    • Because library dependencies are controlled by the content of project.properties (formerly default.properties), ADT must dynamically add and remove these virtual source folders whenever a project is opened and closed.
    • Source-based library prevents distribution of re-usable components(?) unless one is willing to include the source code.
  • In cases...
    • A resource ID is defined in both the application and the library
      • The tools ensure that the resource declared in the application gets priority and that the resource in the library project is not compiled into the application .apk. (or the library with highest priority, and discard the other resource?)
      • This gives your application the flexibility to either use or redefine any resource behaviors or values that are defined in any library.
      • Be aware that common resource IDs are likely to be defined in more than one project and will be merged, with the resource from the application or highest-priority library taking precedence.
    • When two libraries referenced from an application define the same resource ID
      • The tools select the resource from the library with higher priority and discard the other.
  • At build time, the libraries are merged with the application one at a time, starting from the lowest priority to the highest.

Previously (< r14)
Library projects were handled as extra resource and source code folders to be used when compiling the resources and the application’s source respectively. While this worked fine for most cases, there were two issues.
  1. Developers asked us for the ability to distribute a library as a single jar file that included both compiled code and resources. The nature of Android resources, with their compiled IDs prevented this.
  2. The implementation of the library projects was extremely fragile in Eclipse. Adding extra source folders outside of the project folders is non-trivial when it needs to be handled automatically, in a way that doesn’t expose a user’s local installation path (which is required for people working in teams through a source control system such as SVN or git).
To fix all of these issues, we have decided to move to library projects generating a jar file that is directly used by other projects.

The first impact of this change
  • Had to change the way resource IDs are generated.
  • The main projects and all required libraries
    • The resource IDs will still be generated as final static int in the final R class generated in the main project with the resources.
  • The new library project
    • The resource IDs generated by libraries to be non final.
  • Note
    • In a regular projects
      • Resource IDs are generated as final static int. 
      • These constants then get inlined into the classes that use them. 
      • This means the compiled classes do not access the values stored in, say, R.layout.myui, but instead directly embed the value 0x000042.
    • To make the compiled classes not embed this value and instead access it from the R classes, library project will generate the resources IDs as static int only.
    • This prevents the Java compiler from inlining the values in the library code
  • Therefore prevents usage of the switch statement in the library code.
    • Eclipse provides a refactoring action to convert from switch statements to if/else.

Summary
Library projects containing the jar file directly instead of the source code.(Support in r15)

Related
[Android] export android project 為 jar 檔


By the way
  • /res/xml
    • 存儲xml格式的文件。
    • 會被編譯成二進制格式放到最終的apk裡。
    • 可以通過R類來訪問這裡的文件,並且解析裡面的內容。
  • /res/raw
    • 這裡的文件會原封不動的存儲到設備上。
    • 不會被編譯為二進制形式,訪問的方式也是通過R類。
  • /assets
    • 不會被編譯成二進制形式之外。
    • 訪問方式是通過文件名,而不是資源ID。
    • 可以在這裡任意的建立子目錄,而/res目錄中的資源文件是不能自行建立子目錄的。

Pending Study Issues
  • The detail about eclipse export java/android jar.


* Reference
- Android Application, Android Libraries and Jar Libraries **** Although it describes the structure before r14 but it is still very worth to read.
- ADT Plugin for Eclipse | Android Developers
- Android Developer Tools
- Build changes in revision 14 - Android Tools Project Site ***
- SDK Tools
- Library Projects
Android Developers Blog: Changes to Library Projects in Android SDK Tools, r14 ***
Managing Projects | Android Developers **
- Building and Running *
- Developing In Eclipse, with ADT
- I am Happy Android,3C: android /res/xml /res/raw /assets

2011年9月27日 星期二

[Android] Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag

Error Message

Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

(發生在 content provider 中開啟 activity 時?)


Solution

Android has 4 components: Activity, Service, ContentProvider and Broadcast.

When Android needs to activate one of this components from your application, it looks if there is already existing running process with your application.

If not, then Android starts new process, initializes it, then it initializes your custom Application instance. And then it activates one of needed components.



Now, let's consider next scenario:

your application declared content provider in AndroidManifest.xml, and Android just about to start your application so you can provide some data to another foreground application.
and Android just about to start your application so you can provide some data to another foreground application.
Content Provider request is sent

  1. Your application wasn't running, and Android starts new process for it.
  2. Your custom Application instance is created
  3. Application.onCreate() is called.
  4. You start an activity
  5. Your Content Provider receives request

Somebody just wanted to connect to your content provider, but your application started an Activity instead. Same true for starting background Service and sometimes broadcast receivers.

Activity entends Context, and Override startActivity(). 如果使用 activity 中的 startActivity(),不會有任何限制,而如果使用 Context 的 startActivity(),就必須是在另一個新的 task. (?)

That's because you need to start new task when Activity is started outside of Activity context. But I strongly recommend to not start Activity from your Application'sonCreate().

Because Android guarantees that Application will be created only once and before any other component


* Reference
- startActivity的requires new task异常解析 - Android - mobile - ITeye论坛
- Android Application vs Activity - Stack Overflow **

[AndroidStorage] Content Provider 圖解







* Reference
- Byron's blog - Android 数据操作(个解)

2011年9月17日 星期六

[Android] RAM and ROM

[RAM]

* General Definition
  • Random Access Memory,隨機存取記憶體,也就是暫存記憶體,類似DDR。
  • 是與 CPU 直接交換資料的記憶體,也叫主記憶體。
  • 可隨時讀寫,速度快,通常做為 OS 或其他應用程式執行時的暫存位置。


* Android Platform
  • 部份的 RAM 會挪為系統或硬體所使用,不同的硬體所佔用的空間會不同
  • ex: Qualcomm 會佔用的比 TI OAMP(ex: milestone2) 的多。
  • 除非自行刷 ROM,否則這部份幾乎是不可能會被釋放。


[ROM]

* General Definition
  • Read Only Memory,唯讀記憶體,是一種半導體記憶體,類似電腦硬碟。
  • 一旦儲存資料就無法再將資料改變或刪除,且資料也不會因為關閉電源而消失。
  • 在電子或電腦系統中,通常用於儲存不需經常變更的程式或資料。


* Android Platform
  • 在 android 中可分為三部份:
    1. /data: 放一般 end user 所安裝的 apps。
    2. /system: 放 google 或系統廠商所 pre-install 的 apps。
    3. /cache: 系統程式所使用的快取空間。
  • /system 可藉由 root 把 pre-install 的 apk 移除到別的地方,來釋放空間。
  • 而 /data and /cache 受硬體限制,除非自行刷 ROM,再用指令重新分配空間。


[Overview]
大略的說,RAM 用來執行程式,ROM 用來儲存。


* 可觀看 android 系統資訊的 app



* Reference
- Mobile01 如何觀看Android手機的可用RAM與ROM大小 **
- 可以不要再把RAM跟ROM 傻傻分不清楚了! - Mobile01

2011年8月27日 星期六

[Android] SharedPreferences

* 輕量級以 xml 儲存的方式

* 會放在 /data/data/package name/shared_prefs

* global variable

* xml 處理時 Dalvik 會用底層 xml parser 解析