2011年3月29日 星期二

EntityManager 與 Entity

[EntityManager]

* JPA中要對資料庫進行操作前,必須先取得EntityManager實例,這有點類似JDBC在對資料庫操作之前,必須先取得Connection實例,EntityManager是JPA操作的基礎,它不是設計為執行緒安全(Thread-safe)。

* EntityManager主要在管理Entity實例生命週期,透過EntityManager,對Entity實例的操作,可以對應至資料庫進行新增、查找、修改、刪除、重清等動作

* 新增: 使用 EntityManager 的 persist(),這也會讓Entity實例處於Managed狀態,ex:
User user = new User(); // 設定 user 相關屬性
entityManager.persist(user);

* 若要取得資料表中的資料: 使用EntityManager的 find(),指定主鍵物件與Class實例來取得對應的資料並封裝為物件,查找回的物件會處於Managed的狀態,ex:
User user = entityManager.find(User.class, id);

* 若資料庫中已有對應資料,則要修改資料有幾種方式:
  • 若物件是在Managed狀態,例如查找物件之後,直接更新物件,在交易確認之後,物件的更新就會反應至資料表之中:
User user = entityManager.find(User.class, id);
user.setName("Justin Lin");
  • 若物件是在Detached狀態
    • 可使用EntityManager的 merge() 將物件轉至生命周期的Managed狀態,合併物件上之變更:
// 若 user 狀態有所變動
entityManager.merge(user);
    • 或先使用merge()方法將Detached狀態的Entity實例轉至Managed的狀態,再更新物件,在交易確認之後,物件的更新就會反應至資料表之中:
User user1 = entityManager.merge(user);
user1.setName("Justin Lin");

* 刪除資料表中的資料
  • 物件必須是在Managed的狀態,ex:
    • 用EntityManager的find()方法查找物件,以查找到的物件配合remove()方法來移除
    • 或是使用merge(()方法將Entity處於Managed狀態再用remove()移除,移除之後,物件對應不到資料表格中實際的資料,處於Removed狀態:

User user = entityManager.find(User.class, id);
entityManager.remove(user);

* refresh(): 若在載入某個Entity實例之後,而資料表格因另一個操作而發生變動,可以使用此方法,將資料表格的更動載入Entity實例中。

* flush(): 強制EntityManager中管理的所有Entity對應的資料表格與Entity的狀態同步。

* clear(): 可以將EntityManager所管理的Entity實例清除,使Entity處於Detached狀態。

* Persistence Context
  • 預設為Transaction-scoped:
    • 在EntitySessionBean方法開始前會起始交易,結束後停止交易
    • Persistence Context的存活範圍在交易之間,也就是Entity實例在交易完成之後,將會不受EntityManager的管理,將不在是Managed狀態,而處於Detached狀態
  • 每個EntityManager都與一個 Persistence Context 關聯。
  • EntityManager不直接維護Entity,而是將之委托給Persistence Context,Persistence Context中會維護一組Entity實例。
  • 每個Entity在Persistence Context為Managed狀態,Entity實例會有Managed、Detached、Removed狀態。

* 可以在使用@PersistenceContext時,指定type屬性為PersistenceContextType.EXTENDED(預設為PersistenceContextType.TRANSACTION), 使Persistence Context為Extended Persistence Context,在EntityManager實例存活期間,Entity始終受到PersistenceContext的管理,Extended Persistence Context只能用於Stateful Session Bean中,Entity會一直受EntityManager的PersistenceContext管理,直到Stateful Session Bean結束而EntityManager關閉(close)為止。

* 可以想像指定type屬性為PersistenceContextType.EXTENDED 時,一旦進入EntityManager的管理,Entity一直處於Managed的狀態

* Application-Managed EntityManager,則其行為類似於以上說明的Extended-scoped EntityManager,也就是Persistence Context是隨著EntityManager的關閉而失效,也就是當EntityManager關閉後,Entity就不再為Managed狀態。


* Reference
- EJB3 Gossip: 使用 EntityManager
- EJB3 Gossip: Entity 生命週期
- EJB3 Gossip: EntityManager 範圍

JPA Overview

[Definition]

* Java Persistence API (Java 持久層/永續層 API)

* 通過 註解(Annotation, JDK5.0) 或 XML 描述方式,將 物件-關聯表的映射關係 (O-R Mapping / ORM)和運行期 Entity object 持久化到資料庫中去。

* Object/Relational Mapping (ORM)
  • 簡單的說就是將 Java 中的物件與物件關係,映射至關聯式資料庫中的表格與表格之間的關係
  • 使用JPA,底層可以使用不同廠商的ORM實作,而介面則是JPA的標準,ex:
    • NetBeans + Glassfish,則預設的底層實作為TopLink。
    • JBoss的工具其底層實作則為Hibernate

* Persistence in this context covers three areas:
  • the API itself, defined in the javax.persistence package
  • the Java Persistence Query Language (JPQL)
  • object/relational metadata

* 持久性/永續層
  • 相對於只能存活於 JRE Heap 中的 object 來說, 需要能將大量的 object 資訊與 state 保存在一個儲存體中, 提供經常性重複存取物件屬性的 data 機制, JPA 即提供了一個 Java 標準的 Persistence 解決方案.
  • Persistence 的儲存標的物可以是 file 或是 DB.


[Annotation]

* @Entity: 成為 JPA 的 Entity 類別,或者 XML 映射中有對應的 元素。

* @Table: 標示這個Entity類別對應的資料表格,若類別名稱與表格名稱相同,則可以省略,預設會將類別名稱對應至同名的表格,Entity類別必須實作Serializable介面。

* @Id: 使用此標註在資料成員或Getter方法上,使每個Entity類別必須有獨一無二的識別屬性,並與資料表格的主鍵相對應。

* @GeneratedValue: 可以選擇主鍵的產生策略,ex: @GeneratedValue(strategy = GenerationType.AUTO),在這邊利用資料庫本身的自動產生策略,由底層的資料庫來提供。

* @Column: 若成員名稱與表格欄位名稱一樣,則會自動對應,若不同,則可以使用@Column來指定欄位名稱。


[Implement]

  • 為了JPA必須設定資料庫連結與底層實作的一些細節,您要在META-INF下撰寫一個 persistence.xml
  • 建立EntityManagerFactory,EntityManagerFactory內含設定資訊,負責管理 EntityManager,而這樣的方式所取得的EntityManager,稱之為 Application-Managed EntityManager
  • 取得EntityManager後,可透過getTransaction()取得 EntityTransaction
    • EntityTransaction 負責管理交易,透過EntityManger的persist()方法來儲存User物件,EntityManager會自動將對應的成員儲存至對應的資料表格欄位,
    • 若透過EntityManager的find()方法,指定主鍵來查找資料並封裝為User物件,基本上所有的EntityManager操作,要在交易中完成,但find()可以不用在交易中完成,只不過若不在交易中使用find()方法,則查找回來的Entity將立刻不在EntityManager的管理之中(也就是處於Detached狀態

* 若交易過程中發生錯誤,可以捕捉例外,執行EntityTransaction的rollback()方法來撤回交易。
EntityManager entityManager = 
JPAUtil.getEntityManagerFactory().createEntityManager();
EntityTransaction etx = entityManager.getTransaction();
etx.begin();
entityManager.persist(user);
etx.commit();
entityManager.close();

* 若以Java EE容器來管理JPA相關資源,可以使用資源注入的方式取得EntityManager,並可由容器來為您管理Persistence Context,每個EntityManager會關聯至一個Persistence Context,容器會管理Persistence Context的存活範圍,ex: Transaction-scoped或Extended-scoped,Persistence Context管理一組Entity。

* Container-Managed EntityManager
  • 使用 @PersistenceContext 注入EntityManager實例,所取得的EntityManager。
  • unitName屬性指定了persistence.xml中的Persistence Context名稱,Persistence Context預設為Transaction-scoped,也就是在方法開始前會啟始交易,結束後停止交易,Persistence Context的存活範圍在交易之間。
* EntityManager不是Thread-safe,所以要注意在多執行緒下共用存取的同步問題,ex: 使用Stateful Session Bean,讓每個客戶端取得一個Session Bean實例,並獨自使用一EntityManager。


[persistence.xml]

* transaction-type屬性為JTA,並透過設置容器端管理的Data Source之JNDI名稱,這必須在容器端先定好,JDBC資源與Connection Pool等。

* 若要直接在Servlet中使用JPA:

  • 要記得的是,EntityManager不是Thread-safe,所以切記,不可直接將EntityManager注入Servlet中成為物件成員之一,Servlet被共用存取的情況下,會有資料共用存取的問題。
  • 有兩種方式:
    • Container-Managed Entity: 透過在類別上宣告@PersistenceContext並設定JNDI名稱來查找。
    • Application-Managed EntityManager: 透過 @PersistenceUnit 注入EntityManagerFactory並用其取得EntityManager。

* @PersistenceContext的name名稱將作為 JNDI 查找名稱,從unitName 設定得知,實際上查找到的是中對應的定義,Servlet中使用JNDI查找name名稱以取得 EntityManager實例,並透過注入的UserTransaction啟用交易,在交易中進行持久化動作。

* 在Java EE模組中,Persistence Unit會有個獨一無二名稱,容器會以該名稱建立EntityManagerFactory,並用其建立EntityManager,一個persistence.xml中可以定義多個Persistence Unit,以名稱作為區隔。

* 若是將 Persistence Unit 定義在 EJB-JAR 或 WAR 模組中,則 Persistence Unit 的可見範圍僅在該模組之中,若是定義在 EAR 中,則 Persistence Unit的可見範圍為整個應用程式

* 若不使用Annotation來標註Entity類別,則可以將對應關係定義在 orm.xml 中。



* Reference
- EJB3 Gossip: 第一個 JPA (單機客戶端)
- EJB3 Gossip: 第一個 JPA(容器管理)
- EJB3 Gossip: 在 Servlet 中直接使用 JPA
- EJB3 Gossip: 部署 JPA
- Java Persistence API
- (教學簡報分享) JPA.101 JPA 簡介與教學範例
- 開源框架:Hibernate Gossip

2011年3月28日 星期一

JDK PATH

* JDK N Update XX,
  • N: JDK版本號
  • Update: 在發佈JDK之後,每隔二到三個月會針對使用者回報的BUG進行修正,並發佈一個修正版JDK
  • XX: 指該JDK是該版本發佈以來第幾個修正版。

* JDK就包括了JRE,JRE包括了Java SE API與JVM。

* PATH
  • 在一個可以允許多人共用的系統中,系統環境變數的設定,會套用至每個登入的使用者
  • 使用者環境變數則只影響個別使用者。
  • 當你開啟一個文字模式時,所獲得的環境變數,會是系統環境變數再「附加」上使用者環境變數。如果使用SET指令設定環境變數,則以SET所設定的結果決定。



* Reference
- 來安裝 JDK
- PATH 是什麼?

[Resources] Backward Compatibility for Applications

* Should add a to the application's manifest, to ensure your app won't be installed on older devices.

* Suppose there's a simple new call you want to use, like android.os.Debug.dumpHprofData(String filename). The Debug class has existed since Android 1.0, but the method is new in Anroid 1.5 (API Level 3). If you try to call it directly, your app will fail to run on devices running Android 1.1 or earlier.

* The simplest way to call the method is through reflection.
  • This requires doing a one-time lookup and caching the result in a Method object. 
  • Using the method is a matter of calling Method.invoke and un-boxing the result.
* For each additional method you want to call, you would add an additional private Method field, field initializer, and call wrapper to the class.

* Using a wrapper class
  • The idea is to create a class that wraps all of the new APIs exposed by a new or existing class. 
  • Each method in the wrapper class just calls through to the corresponding real method and returns the same result.
* If the target class and method exist, you get the same behavior you would get by calling the class directly,

* If the target class or method doesn't exist, the initialization of the wrapper class fails, and your application knows that it should avoid using the newer calls.

* When wrapping an existing class that now has new methods, you only need to put the new methods in the wrapper class. Invoke the old methods directly. The static initializer in WrapNewClass would be augmented to do a one-time check with reflection.

(?)


* Reference
- Backward Compatibility for Applications

2011年3月26日 星期六

3G, GSM, CDMA, WCDMA, WAP, GPRS...

[1G - 2G - 3G]

* G 表示 Generation。

* 1G:
  • 最著名的規格是 AMPS (Advanced Mobile Phone System),ex: 黑金剛即屬此種規格下的產品。
  • 其實 Advanced 指的進階,只是比一般的室內電話更進步一點,所以就跟室內電話一樣。
  • AMPS也是類比的語音傳輸,而AMPS所採用的處理技術為 FDMA (Frequency Division Multiple Access,分頻多工存取)。

* 2G:
  • 從 1G 進步到 2G,主要的改變是從類比訊號轉為數位訊號
  • 其中的規格並不只有一種,所採用的技術也可以粗淺的分為兩種。
    • TDMA (Time Division Multiple Access,分時多工存取): 如歐洲、台灣等地所使用的 GSM(機卡分離的設計) (Global System For Mobile Communication)與日本採用的 PDC (Personal Digital Cellular)。
    • CDMA (Code Division Multiple Access,分碼多工存取,機卡合一): 由美國 Qualcomm 公司新發展出的傳輸標準,此時的 CDMA 其實仍然屬於 2G 的範圍,後來則被通稱為所謂的窄頻 CDMA (narrow-band CDMA),以便於跟 3G 的新一代 CDMA 技術做區別。

* 3G
  • 3G 與 2G 的差異,最主要的地方在於資料傳輸的速度,換句話說也就是頻寬的增加
  • 3G 的通訊標準不一而足,但主要都是從 CDMA 技術為藍圖而發展出來的,最著名的包括了 W-CDMA (Wide-band CDMA,也稱為CDMADirectSpread)、 CDMA 2000、以及大陸積極推動的 TDS-CDMA。這些都只是資料傳輸技術的不同。
  • 因為類比式系統有通話容量的限制,又沒有加密機制,傳輸過程中容易被竊聽,而且只提供純語音通話服務,不能傳遞文字簡訊,於是美洲地區從 AMPS 發展出 CDMA One,這是第一代的窄頻 CDMA,可以提供 64Kbps 到 115Kps 的傳輸速率。

* WCDMA (Wide band Code Division Multiple Access 寬帶分碼多工)
  • 是一種 3G 蜂窩網絡。
  • 使用的部分協議與 2G GSM 標準一致。
  • 是一種利用碼分多址復用 (或者 CDMA 通用復用技術,不是指 CDMA 標準)方法的寬帶擴頻 3G 移動通信空中接口。
  • 其支持者包括歐美的愛立信、阿爾卡特、諾基亞、朗訊、北電,以及日本的NTT、富士通、夏普等廠商。
  • 這套系統能夠架設在現有的 GSM 網路上,對於系統提供商而言可以較輕易地過渡,而GSM系統相當普及的亞洲對這套新技術的接受度預料會相當高。

* FOMA (Freedom Of Multimedia Access)
  • 並不是一種技術,而是日本 NTT DoCoMo 所推出的 3G 行動上網服務
  • 是全球第一個真正商業運行的 3G 服務
  • 採用 W-CDMA 的技術,基地台設備則由 Ericsson 提供
  • 所以拿 FOMA 來跟 W-CDMA、 CDMA 2000 或是 TDMA 來比是有概念化上的缺失,就好像拿橘子跟椅子比一樣,而日本第二大系統業者 KDDI 所推動的 3G 服務,則是以 CDMA 2000 為架構


[WAP and GPRS]
所謂的 WAP 與 GPRS,其實兩者之間也無法真正被拿來作比較,這也是目前很多很多人的一個誤解,以為 GPRS 是拿來與 WAP 相提並論的。

* WAP (Wireless Application Protocol,無線應用協定)
  • 是一種通訊協定,就好像 internet 上用的是 HTTP 一樣,而在 WAP 協定下所使用的程式語言則為 WML (Wireless Mark-Up Language)
  • 一般我們說的 WAP 手機,其實應該是指 WAP Over Circuit-Switched Data,或是簡單一點說成 WAP Over GSM Circuit,但我們所說的 GPRS 手機上網,其實是屬於 WAP Over Packet-Switched Data,或是 WAP Over GPRS
  • 從這邊我們可以看出來,GPRS 相對的概念其實並不是 WAP,而應該是傳統 GSM 線路的傳輸方式

* GPRS (General Packet Radio Service,通用封包無線傳輸服務)
  • 根本上的技術是從之前 GSM 線路傳輸的 9.6Kbps,改用封包傳輸的技術,分開傳送、同步處理,使得傳輸速度得以大幅度提升,理論上可以達到 100Kbps,但目前實作出來的速度約略是在 40 ~ 50 Kbps 左右(依所利用到的 Time Slot 而定)。
  • 至於為什麼 GSM 線路傳輸的速度只有 9.6Kbps 而不是 96Kbps?
    • 一開始 GSM 規格在制定的時候,一個 Time Slot 所劃分的頻寬扣掉容錯碼後就只剩 9.6Kbps (因為一開始 GSM 仍然是拿來講電話的,當初誰會想到要用這玩意上網?),而 GPRS 技術則可以一次利用單一頻率中全部的八個時槽來傳輸資料,至於傳送的方式則是拆開成封包同步傳輸,後端再把封包組裝起來形成原始的資料 (可想像成 WinRAR 的多個壓縮檔)。
  • 但這邊又有一個技術要跟 GPRS 釐清不同的地方,那就是所謂的 HSCSD (High Speed Circuit Switched Data Service),HSCSD 與 GPRS 類似的地方是都能同時使用超過一個的時槽進行資料傳輸,但相異的地方在於 HSCSD 仍然是採用傳統 GSM 的線路傳輸技術而非 GPRS 的封包傳送。



* Reference
- 問問一些觀念問題 2G 2.5G 3G CDMA WCDMA
- 3G - CDMA, WCDMA, TD-SCDMA
- CDMA和WCDMA差在哪裡?
- 什麼是GSM、CDMA、WCDMA、PHS?

[LVL] AIDL

[IPC]

* IPC: Inter-Process Communication

* 程序和程序間是需要通訊的,我們稱此能力為程序間通訊。

* IPC 就是數種在 MultiProcess 下相互溝通的方法,其實不只是 process,甚至可推及 thread 間及 computer 間的溝通。這些技術包含像 synchronization, message passing, shared memory, memory-mapped files, pipe, socket…等等。


[AIDL]

* AIDL: Android Interface Definition Language

* 可以協助我們快速地建構Android程序間的通訊介面 (如在Windows系統中存在IPC管道服務、MailSolt郵槽、消息等方法)。

* Using AIDL is necessary only if:
  • You allow clients from different applications to access your service for IPC
  • Want to handle multithreading in your service.

* Be aware that calls to an AIDL interface are direct function calls. You should not make assumptions about the thread in which the call occurs. What happens is different depending on whether the call is from a thread in the local process or a remote process.

* Calls made from the local process are executed in the same thread that is making the call. If this is your main UI thread, that thread continues to execute in the AIDL interface. If it is another thread, that is the one that executes your code in the service. Thus, if only local threads are accessing the service, you can completely control which threads are executing in it (but if that is the case, then you shouldn't be using AIDL at all, but should instead create the interface by implementing a Binder).

* In other words, an implementation of an AIDL interface must be completely thread-safe.

* When used, a remote call does not block; it simply sends the transaction data and immediately returns. The implementation of the interface eventually receives this as a regular call from the Binder thread pool as a normal remote call. If oneway is used with a local call, there is no impact and the call is still synchronous.

* To create a bounded service using AIDL, follow these steps:
  1. Create the .aidl file:
    This file defines the programming interface with method signatures.
  2. Implement the interface:
    The Android SDK tools generate an interface in the Java programming language, based on your .aidl file. This interface has an inner abstract class named Stub that extends Binder and implements methods from your AIDL interface. You must extend the Stub class and implement the methods.
  3. Expose the interface to clients:
    Implement a Service and override onBind() to return your implementation of the Stub class.

* The parameters and return values can be of any type, even other AIDL-generated interfaces.

* Each .aidl file must define a single interface and requires only the interface declaration and method signatures.

* There are a few rules you should be aware of when implementing your AIDL interface:
  • Incoming calls are not guaranteed to be executed on the main thread, so you need to think about multithreading from the start and properly build your service to be thread-safe.
  • By default, RPC calls are synchronous. If you know that the service takes more than a few milliseconds to complete a request, you should not call it from the activity's main thread, because it might hang the application (Android might display an "Application is Not Responding" dialog)—you should usually call them from a separate thread in the client.
  • No exceptions that you throw are sent back to the caller.

* Supporting the Parcelable interface is important because it allows the Android system to decompose objects into primitives that can be marshalled across processes.

* To create a class that supports the Parcelable protocol, you must do the following:
  • Make your class implement the Parcelable interface.
    Implement writeToParcel, which takes the current state of the object and writes it to a Parcel.
  • Add a static field called CREATOR to your class which is an object implementing the Parcelable.Creator interface.
  • Finally, create an .aidl file that declares your parcelable class.
  • If you are using a custom build process, do not add the .aidl file to your build. Similar to a header file in the C language, this .aidl file isn't compiled.

* Here are the steps a calling class must take to call a remote interface defined with AIDL:
  1. Include the .aidl file in the project src/ directory.
  2. Declare an instance of the IBinder interface (generated based on the AIDL).
  3. Implement ServiceConnection.
  4. Call Context.bindService(), passing in your ServiceConnection implementation.
  5. In your implementation of onServiceConnected(), you will receive an IBinder instance (called service). Call YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type.
  6. Call the methods that you defined on your interface. You should always trap DeadObjectException exceptions, which are thrown when the connection has broken; this will be the only exception thrown by remote methods.
  7. To disconnect, call Context.unbindService() with the instance of your interface.

* A few comments on calling an IPC service:
  • Objects are reference counted across processes.
  • You can send anonymous objects as method arguments.



* Reference
- Android Interface Definition Language (AIDL)
- 運用AIDL來打造Android程序間的通訊
- [轉]Android 的AIDL是啥?
- 一千零一夜之 Android Binder
- Android的IPC機制及多線程技術 **
- 深刻解析 Android 的 AIDL 介面(一) **
- Inter-Process Communication (IPC)

2011年3月25日 星期五

[LVL] Application Licensing

* Your applications can query Android Market at run time to obtain their licensing status for the current user, then allow or disallow further use as appropriate.

* Check License Flow:
  • An application checks the licensing status
  • The Market server signs the licensing status response using a key pair that is uniquely associated with the publisher account.
  • Your application stores the public key in its compiled .apk file and uses it to verify the licensing status response.

* In the licensing service
  • An application does not query the licensing server directly
  • But binding to a service provided by the Android Market application
  • Initiating a license check request calls the Android Market client over remote IPC to initiate a license request.
  • The Android Market service then handles the direct communication with the licensing server and finally routes the response back to your application.

* In the license request:
  1. The application: provides its package name and a nonce that is later used to validate any response from the server, as well as a callback over which the response can be returned asynchronously.
  2. The Android Market client: has greater permissions than the application, collects the necessary information about the user and the device (ex: the device's primary Google account username, IMSI, and other information) It then sends the license check request to the server on behalf of the application.
  3. The server:
    • Evaluates the request using all available information, attempting to establish the user's identity to a sufficient level of confidence.
    • Then checks the user identity against purchase records for the application and returns a license response, which the Android Market client returns to the application over the IPC callback.

* License responses secured through public key cryptography.
  • The server signs the license response data using an RSA key pair that is shared exclusively between the server and the application publisher.
  • The licensing service generates a single licensing key pair for each publisher account and exposes the public key in the account's profile page. (The publisher copies the public key and embeds it in the application source code, then compiles and publishes the .apk.)
  • The server retains the private key internally and uses it to sign license responses for applications published on that account.
  • When the application receives a signed response, it uses the embedded public key to verify the data. (The use of public key cryptography in the licensing service makes it possible for the application to detect responses that have been tampered with or that are spoofed.)


[LVL API]

* The key LVL interfaces are:
  • Policy: your implementation determines whether to allow access to the application
    • The implementation can evaluate the various fields of the license response and apply other constraints, if needed.
    • The implementation also lets you manage the handling of license checks that result in errors, such as network errors.
    • Declares two methods: allowAccess() and processServerResponse() which are called by a LicenseChecker instance when processing a response from the license server. It also declares an enum called LicenseResponse, which specifies the license response value passed in calls to processServerResponse().
  • LicenseCheckerCallback: your implementation manages access to the application
    • Based on the result of the Policy's handling of the license response.
    • Your implementation can manage access in any way needed, including displaying the license result in the UI or directing the user to purchase the application (if not currently licensed).

* ServerManagedPolicy
  • A flexible Policy that uses settings provided by the licensing server to manage response caching and access to the application while the device is offline (such as when the user is on an airplane).
  • Is highly recommended.

* Integrating the LVL with your application code involves these tasks:
  1. Adding the licensing permission your application's manifest.
  2. Implementing a Policy — you can choose one of the full implementations provided in the LVL or create your own.
  3. Implementing an Obfuscator, if your Policy will cache any license response data.
  4. Adding code to check the license in your application's main Activity
  5. Implementing a DeviceLimiter (optional and not recommended for most applications)

* AESObfuscator:
  • Provides secure obfuscation of data by using AES to encrypt and decrypt the data as it is written to or read from storage.
  • Seeds the encryption using three data fields provided by the application:
    • A salt: an array of random bytes to use for each (un)obfuscation.
    • An application identifier string, typically the package name of the application.
    • A device identifier string, derived from as many device-specific sources as possible, so as to make it as unique.

* To add the license check and handle the response, you must:
  1. Add imports
  2. Implement LicenseCheckerCallback as a private inner class
  3. Create a Handler for posting from LicenseCheckerCallback to the UI thread
  4. Instantiate LicenseChecker and LicenseCheckerCallback
  5. Call checkAccess() to initiate the license check
  6. Embed your public key for licensing
  7. Call your LicenseChecker's onDestroy() method to close IPC connections.

* A license check consists of two main actions:
  1. A call to a method to initiate the license check: in the LVL, this is a call to the checkAccess() method of a LicenseChecker object that you construct.
  2. A callback that returns the result of the license check: this is a LicenseCheckerCallback interface that you implement. The interface declares two methods, allow() and dontAllow(), which are invoked by the library based on to the result of the license check. You implement those two methods with whatever logic you need, to allow or disallow the user access to your application.

* During a license check, the LVL:
  • Passes the request to the Android Market application, which handles communication with the licensing server.
  • Passes the request over asynchronous IPC (using Binder) so the actual processing and network communication do not take place on a thread managed by your application.
  • Similarly, when the Android Market application receives the result, it invokes a callback method over IPC, which in turn executes in an IPC thread pool in your application's process.

* The LVL calls your LicenseCheckerCallback methods from the background thread.

* Note that LicenseChecker calls the LicenseCheckerCallback methods from the UI thread only if there is valid license response cached locally. If the license check is sent to the server, the callbacks always originate from the background thread, even for network errors.

* Finally, to let the LVL clean up before your application Context changes, add a call to the LicenseChecker's onDestroy() method from your Activity's onDestroy() implementation. The call causes the LicenseChecker to properly close any open IPC connection to the Android Market application's ILicensingService and removes any local references to the service and handler.


[Test]

* Setting up your environment for licensing involves these tasks:
  • Downloading the latest SDK, if you haven't already done so
  • Setting up the runtime environment for development
  • Downloading the Market Licensing component into your SDK
  • Setting up the Licensing Verification Library
  • Including the LVL library project in your application


* Reference
- Application Licensing

[Resources] Copy and Paste

* The clip object (ClipData.Item) can take one of three forms:
  1. Text
  2. URI
  3. Intent

* The clipboard holds only one clip object at a time. When an application puts a clip object on the clipboard, the previous clip object disappears.

* To add data to the clipboard, you create a ClipData object that contains
  1. A description of the data: A ClipDescription object.
  2. The data itself: One or more ClipData.Item objects.

* A ClipDescription object
- Contains an array of available MIME types for the clip's data: when you put a clip on the clipboard, this array is available to pasting applications, which can examine it to see if they can handle any of available the MIME types.

* To copy data
  1. An application puts a ClipData object on the ClipboardManager global clipboard.
  2. The ClipData contains one or more ClipData.Item objects and one ClipDescription object.

* To paste data
  1. An application gets the ClipData, gets its MIME type from the ClipDescription
  2. And gets the data either from the ClipData.Item or from the content provider referred to by ClipData.Item.

* You should verify that the clipboard contains a clip and that you can handle the type of data represented by the clip.


* Reference
- Copy and Paste

2011年3月20日 星期日

[Resources] Avoiding Memory Leaks

* Most of the time due to the same mistake to memory leaks: keeping a long-lived reference to a Context.

* A Context is used for many operations but mostly to load and access resources. In a regular Android application, you usually have two kinds of Context, Activity and Application.

* This means that views have a reference to the entire activity and therefore to anything your activity is holding onto; usually the entire View hierarchy and all its resources.

* There are two easy ways to avoid context-related memory leaks.
  1. To avoid escaping the context outside of its own scope.
  2. To use the 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() or Activity.getApplication().

* In summary, to avoid context-related memory leaks, remember the following:
  1. 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)
  2. Try using the context-application instead of a context-activity.
  3. 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
  4. A garbage collector is not an insurance against memory leaks



* Reference
- Avoiding Memory Leaks

[LVL] Publishing on Android Market

* To register as an Android Market developer and get started with publishing, visit the Android Market publisher site:

http://market.android.com/publish

* With Android Market Licensing, your applications can query Android Market at runtime to obtain the licensing status for the current user, then allow or disallow further use of the application as appropriate.



* Reference
- Publishing on Android Market

2011年3月17日 星期四

[AJAX] Introduction

* Definition
  • 不同步的 JavaScript 及 XML(Asynchronous JavaScript And XML)。
  • 2005 年由 Google 推廣來的編程模式,但並不是一種新的编程語言,而是一種使用現有標准的新方法,用於創建快速動態網頁。
  • 基於 JavaScript 和 HTTP 請求(HTTP requests),在無需重新加載整個網頁的情况下,通過在後台與 server 進行少量數據交換,能夠更新部分網頁。
  • ex: 新浪微博、Google 地圖、開心網。

* XMLHttpRequest
  • 是 AJAX 的基礎。
  • 用於在後台與 server 交換數據。
  • 但對於 IE5 and IE6 則需要檢查是否支持 XMLHttpRequest 對象。若支持才創建 XMLHttpRequest 對象,若不支持,則是創建 ActiveXObject。

* 在以下情况中,請使用 POST:
  • 無法使用緩存文件(更新 server 上的文件或數據庫)
  • 向 server 送大量數據(POST 没有數據量限制)
  • 發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠

* 使用 async=false 時,不要編寫 onreadystatechange 函数,把代碼放到 send() 語句後面即可。

* 使用 async=true 時,在回應處於 onreadystatechange 事件中的就緒狀態執行的函数。

* onreadystatechange 事件
  • 當請求被送到 server 時,一些當 server 回應已經做好被處理的準備時所需要執行的工作。
  • 當 readyState 改變時,就會觸發 onreadystatechange 事件。
  • readyState 屬性存有 XMLHttpRequest 的狀態信息。
  • 當 readyState 等於 4 且狀態為 200 時,表示回應已就緒。
  • 此事件會被觸發四次,對應著 readyState 的每個變化。

* callback 函數是一種以参數形式傳遞给另一個函數的函數。


* Reference
- W3C AJAX 教程

[jQuery] Overview Note

[Introduction]

* Definition:
  • A JavaScript Library.
  • 為事件處理特别設計的。

* jQuery library 包含以下特性:
  • HTML 元素選取
  • HTML 元素操作
  • CSS 操作
  • HTML 事件函数
  • JavaScript 特效和動畫
  • HTML DOM traversal and modification
  • AJAX
  • Utilities

* Google 的 CDN
<head>
  
</head>

* HTML 元素默認是靜態定位,且無法移動。如需使元素可以移動,請把 CSS 的 position 設置為 relative 或 absolute。


[Selector]

* 基礎語法是:$(selector).action()

* 以 $ 符號做為間接方式,但有可能某些其他 JavaScript Library 中的函数(比如 Prototype)同樣使用 $ 符號而發生符號衝突。因此可以使用 noConflict() 定義自己的名稱來取代 $ 符號,如下:
var jq=jQuery.noConflict()

* 使用 CSS selector 來選取 HTML 元素。ex:
  • $("p") 選取所有<p>元素。
  • $("p.intro") 選取所有 class="intro" 的<p>元素。
  • $("p#demo") 選取 id="demo" 的第一個 <p>元素。

* 使用 XPath 表達式來選擇带有给定屬性的元素。
  • $("[href]") 選取所有带有 href 屬性的元素。
  • $("[href='#']") 選取所有带有 href 值等於 "#" 的元素。
  • $("[href!='#']") 選取所有带有 href 值不等於 "#" 的元素。
  • $("[href$='.jpg']") 選取所有 href 值以 ".jpg" 结尾的元素。

* " * Selector"
  • 表示選取文檔中的每個單獨的元素,包括 html、head 和 body。
  • 如果與其他元素一起使用,該 selector 選取指定元素中的所有子元素。
  • 但某些 bowser 處理 * 的速度缓慢。

* 不要使用數字開頭的 ID 名稱!在某些瀏覽器中可能出问題。

* :empty
  • 選取空的元素。
  • 空元素指的是不包含子元素或文本的元素。
  • 除以下幾種情况之外的元素即是可見元素:
    • display:none
    • type="hidden"
    • Width 和 height 等於 0
    • 隱藏的父元素(同時隱藏所有子元素)

* $("[attribute]")
選擇每個带有指定属性的元素。

* :text: 選取類型為 text 的 <input> 元素。


[Callback function]

* 在當前動畫 100% 完成之後才執行。

* 由於 JavaScript 語句是逐一執行的,所以因為動畫還沒完成,動畫之後的語句可能會產生錯誤或頁面衝突。為了避免這個情况,可以以参數的形式添加 Callback 函數。

* callback 参數是一個在操作完成後被執行的函数。


[Action]

* delegate()
適用於當前或未来的元素(比如由脚本創建的新元素)。

* load()
  • 當指定的元素(及子元素)已加載時,會發生 load() 事件。
  • 此事件適用於任何带有 URL 的元素(比如圖像、脚本、框架)。
  • 根據不同的瀏覽器,如果圖像已被缓存,則也許不會觸發 load 事件。
  • 是一種簡單的(但很强大的)AJAX 函数。語法如下:

$(selector).load(url,data,callback)
// url: 指定數據的 web 地址。
// 只有希望向 server 發送數據時,才需要使用 data 参數; 需要在執行完畢後觸發一個函數時,才需要使用 callback。

* append()
  • 在被選元素的结尾(仍然在内部)插入指定内容。
  • append() 和 appendTo() 作用相同。不同之處在於:内容的位置和selector

* detach()
  • 移除被選元素,包括所有文本和子節點。
  • 會保留 jQuery 對象中的匹配的元素,因而可以在將來再使用這些匹配的元素。
  • 會保留所有绑定的事件、附加的數據,這一點與 remove() 不同。

* remove()
  • 移除被選元素,包括所有文本和子節點。
  • 不會把匹配的元素從 jQuery 對象中删除,因而可以在將來再使用這些匹配的元素。
  • 但除了保留元素本身外,不會保留元素的 jQuery 數據。其他的比如绑定的事件、附加的數據等都會被移除。與 detach() 不同。

* text()
  • 返回或設置被選元素的内容 (inner HTML)。
  • 與 html() 類似,但是不會對 tag 轉譯,皆視為純文字
  • 如果該方法未設置参数,則返回被選元素的當前内容。

* val()
  • 取值时,僅會返回第一個匹配元素的值。
  • 但設值時,會設置所有匹配元素的值。


* Reference
- W3C jQuery 教程

[Javascript] Introduction

什麼是 JavaScript?
  • - 用來向 HTML 頁面添加互動行為。
  • - 一種脚本語言(脚本語言是一種輕量级的编程語言)。
  • - 由數行可執行計算機代碼组成。
  • - 通常被直接嵌入 HTML 頁面。
  • - 是一種解釋性語言(就是说,代碼執行不進行預編碼)。

* 放置位置
  • - in <head>: 當 script 被調用或事件被觸發時,就會執行script。可以確定在要使用前便已經被載入。
  • - in <body>: 頁面載入時就會被執行,生成頁面內容。
  • - External script: 外部 script 中不需要包含  <script> tag,然後將 .js 指定至 <script> 的 "src" 屬性中。


* JavaScript 語句是發給瀏覽器的命令。這些命令的作用是告诉瀏覽器要做的事情

* === 全等: 值與型態都會比較,例: x===5 為 true;x==="5" 為 false


* Reference

[CSS] Introduction

* 放置位置

- external style (.css)
- internal style(位於 <head> 內部)
- inline style(在 HTML 元素內部,有最高的優先權)

* Position: 在使用相對定位時,無論是否進行移動,元素仍然占據原來的空間。因此,移動元素會導致它覆蓋其它框。


* Reference
- W3C CSS 教程

2011年3月15日 星期二

[JSP] Introduction

* Directive
  • <%@              %>
  • 使用指令元素include來包括其它網頁內容時,會在轉譯時期就決定轉譯後的Servlet內容,是一種靜態的指定方式。
  • 標籤的使用,則是執行時期動態將別的網頁包括進來進行回應的方式,使用的網頁與被包括的網頁,各自都生成一個獨立的Servlet。

* 宣告、Scriptlet 與運算式元素
  • Declare: <%!      %>
  • Scriptlet: <%       %>
  • Expression: <%=       %>
  • 容器預設會使用同一個Servlet實例來服務不同使用者的請求,每個請求是一個執行緒,而<%!與%>間宣告的變數對應至類別變數成員,因此會有執行緒共用存取的問題。
  • <%與%>之間所包括的內容,將被轉譯為Servlet原始碼_jspService()方法中的內容。注意!運算式元素中不用加上分號(;)。這個運算式元素在轉譯為Servlet之後,會在_jspService()中產生以下的陳述句:out.print(new Date());

* JSP 生命週期
  • 注意到_jspInit()、_jspDestroy()與_jspService()方法名稱上有個底線,表示這些方法是由容器轉譯時維護,你不應該重新定義這些方法。如果想要作些JSP初始化或收尾動作,則應定義jspInit()或jspDestroy()方法。

* 深入 <jsp:usebean>、<jsp:setproperty> 與 <jsp:getproperty>
  • 如果你使用標籤時沒有指定scope,則預設「」在page範圍中尋找JavaBean,找不到就建立新的JavaBean物件(不會再到request、session與application中尋找)。


* Reference
- 語言技術:Servlet/JSP Gossip

[CSS] Selector

.class {}

#id {}

selector {}

[attr="val"] {}  val需完全相等

[attr~="val"] {}  只要有包含val即生效

selector.class_value {} = selector["attr_value"] {}

[attr^="val"] {}  以val開頭的value
[attr$="val"] {}  以val結尾的value
[attr*="val"] {}  包含val開頭的value

[att|="val"] {}  以val開頭的value


* Reference
- W3C CSS 教程