如何在程式內啟用Google的 Android Application Licensing
壹、下載Android SDK
由於標準的Android SDK並未包含Android Market, 你必須下載the Google APIs Add-On platform, API Level 8 (或以上), from the SDK repository. 只有 Google APIs Add-On, API 8 (release 2) 或更高的版本,才有提供 Android Market 必要的服務. 啟動Android SDK and AVD Manager並下載(如Figure 1)
Figure 1. Google APIs Add-On, API 8 (release 2) or higher 才能讓你在模擬器中測試程式授權的功能
貳、下載the LVL
下載Google 提供的The License Verification Library (LVL)程式庫,選取"Market Licensing"下載(Figure 2).
Figure 2. The Market Licensing package contains the LVL and the LVL sample application.
下載後並完成安裝後,程式庫存放的路徑如下:
<
sdk>/market_licensing/library/
(the LVL library 專案的位置)<
sdk>/market_licensing/sample/
(the example application範例的位置)參、設定The License Verification Library (LVL)專案成為程式庫(Library)
要將LVL專案設為程式庫(Library),才能被其他程式呼叫使用,建立LVL專案就像建立新的專案一樣
一、選取 File > New > Project
二、選擇 Android > Android Project, 按下 Next.
三、選擇project from existing code選項,找出LVL library路徑,如<sdk>/market_licensing/library/(<sdk>指你存放Android SDK的路徑)
四、完成後,在專案瀏覽器(Package Explorer)選取你剛建立的LVL專案,按下右鍵,選取Properties
五、開啟Properties視窗後,至”Library”標籤下選取"is Library",按下OK鍵(如Figure 3.)
完成後,你的LVL程式庫就可以被任何程式呼叫.
Figure 3. Marking a project as an Android library project.
肆、在你要使用Google軟體授權機制的程式中加入本項功能
一、匯入程式庫,在專案瀏覽器(Package Explorer)選取你的程式專案按下右鍵,選取Properties,開啟Properties視窗後,在左邊目錄中選取"Android",將右邊畫下拉至出現”Library”標籤,在右邊選取"Add"按鈕,選取並加入你剛建立的LVL程式庫,按下OK鍵.
二、在AndroidManifest.xml中加入使用權限如下:
<uses-permission android:name="com.android.vending.CHECK_LICENSE"> |
其宣告的方式如下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" ..."> <!-- Devices >= 3 have version of Android Market that supports licensing. --> <uses-sdk android:minSdkVersion="3" /> <!-- Required permission to check licensing. --> <uses-permission android:name="com.android.vending.CHECK_LICENSE" /> ...</manifest> |
注意,由於這是第三方的軟體,SDK tools尚未將此項使用權限合併至AndroidManifest.xml整合工具程式中,無法在IDE系統中選取,必須手動建立
三、選擇授權策略,你可以自訂授權策略或直接採用LVL提供的預設授權策略.若你沒有更好的授權策略,Google建議你最好採用預設授權方式.
四、LVL提供兩種完整的預設授權方式,而且你可以完全不修改直接採用:
•ServerManagedPolicy is 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). For most applications, the use of ServerManagedPolicy is highly recommended. (由授權伺服器管理授權,彈性的授權方式包括已授權者在離線時仍可繼續使用,如無特殊考量,建議採用此項策略)
•StrictPolicy is a restrictive Policy that does not cache any response data and allows the application access only when the server returns a licensed response.(限制性的授權,只要程式未接收到授權伺服器回傳的授權回應,即無法使用)
五、建立你的亂碼化因子
The LVL採用亂碼化因子在執行授權認證時以防止被截取認證碼.該亂碼化因子被稱為AESObfuscator,所以,在程式中必須建立一組20個亂碼值的靜態位元組陣列,提供給授權函式使用,建立如下:
// Generate 20 random bytes, and put them here. private static final byte[] SALT = new byte[] { -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95, -45, 77, -117, -36, -113, -11, 32, -64, 89 }; |
伍、實作授權檢查程式碼到你的程式專案中(以ServerManagedPolicy為例):
一、在程式中匯入必要的類別:
呼叫認證用函式類別
import com.android.vending.licensing.LicenseChecker; import com.android.vending.licensing.LicenseCheckerCallback; |
呼叫預設授權策略執行函式及類別
import com.android.vending.licensing.ServerManagedPolicy; import com.android.vending.licensing.AESObfuscator; |
二、實作自己的LicenseCheckerCallback類別
The LVL提供的LicenseCheckerCallback類別,是一個檢查授權狀態的操作介面,你必須自己完成實作部分,包括allow() 和 disallow()兩個函式的程式處理,The LVL提供的範例結構如下(其餘的部分必須自己完成):
private class MyLicenseCheckerCallback implements LicenseCheckerCallback { public void allow() { if (isFinishing()) { // Don't update UI if Activity is finishing. return; } // Should allow user access. displayResult(getString(R.string.allow)); } public void dontAllow() { if (isFinishing()) { // Don't update UI if Activity is finishing. return; } displayResult(getString(R.string.dont_allow)); // Should not allow access. An app can handle as needed, // typically by informing the user that the app is not licensed // and then shutting down the app or limiting the user to a // restricted set of features. // In this example, we show a dialog that takes the user to Market. showDialog(0); } } |
在執行授權檢查期間, the LVL會要求Android Market程式進行與授權伺服器之間的通訊,The LVL會發出非同步的IPC(處理程序間的通訊方法,使用Binder進行),所以實際的授權認證處理及網路通訊並不會在你的應用程式中進行和被管理.相同地,當Android Market程式接收到授權伺服器傳回的結果時,它會透過IPC喚醒callback方法(該callback方法是在你的程式中所使用並在IPC thread pool中所執行的IPC執行緒 ),
在你的程式中執行授權認證的程序是由LicenseChecker類別透過Android Market程式來進行管理,包括呼叫、傳送程式的請求和接收授權伺服器回傳訊息, LicenseChecker類別更能追踪開放式授權請求並管理此請求是否超時(timeout).這意味著授權程序一經啟動後,就一直在背景中執行.
如果你想要更新你在UI執行緒中進行的LicenseCheckerCallback 方法,你必須啟始一個Handler物件在你的主活動(Main Activity)的onCreate()方法中,以下範例是呼叫
displayResult()
程序透過Handler's post()方法
來更新UI執行緒private Handler mHandler; @Override public void onCreate(Bundle savedInstanceState) { ... mHandler = new Handler(); } |
private void displayResult(final String result) { mHandler.post(new Runnable() { public void run() { mStatusText.setText(result); setProgressBarIndeterminateVisibility(false); mCheckLicenseButton.setEnabled(true); } }); } |
三、啟始LicenseChecker and LicenseCheckerCallback兩個物件
在你的主活動(Main Activity)程式中設定並啟始LicenseChecker and LicenseCheckerCallback兩個物件如下:
public class MainActivity extends Activity { ... private LicenseCheckerCallback mLicenseCheckerCallback; private LicenseChecker mChecker; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // Construct the LicenseCheckerCallback. The library calls this when done. mLicenseCheckerCallback = new MyLicenseCheckerCallback(); // Construct the LicenseChecker with a Policy. mChecker = new LicenseChecker( this, new ServerManagedPolicy(this, new AESObfuscator(SALT, getPackageName(), deviceId)), BASE64_PUBLIC_KEY // Your public licensing key. ); ... } } |
四、呼叫checkAccess()方法來啟始授權檢查
在你的主活動(main Activity)中加入呼叫LicenseChecker 實作中checkAccess()方法的程序,在呼叫程序中將LicenseCheckerCallback實作物件當作傳遞參數放在checkAccess()方法中呼叫,如果你想要在呼叫checkAccess()方法前,自己控制或管理任何特定的UI效果或狀態,以下the LVL 所提供的doCheck()範例程序將是很有用的.
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // Call a wrapper method that initiates the license check doCheck(); ... } ... private void doCheck() { mCheckLicenseButton.setEnabled(false); setProgressBarIndeterminateVisibility(true); mStatusText.setText(R.string.checking_license); mChecker.checkAccess(mLicenseCheckerCallback); } |
五、嵌入你軟體授權的公開金鑰
每一個發佈商帳號, Android Market service將會自動產生一組2048-bit RSA公開/私密金鑰( public/private key pair)用來執行授權認證之用, 一個發佈商只有一組唯一的公開/私密金鑰,發佈商可以透過其發佈商帳號在他所有程式中使用,雖然是與發佈商帳號結合,這組金鑰對組與你所簽發程式的金鑰並不相同.
雖然Android Market發佈商網站在程式開發者簽入的發佈商帳號中,揭露了軟體授權驗證用的公開金鑰,但是它會將所有使用者的私密金鑰隱藏在安全的地方,當一個在發佈商帳號中被發佈的程式要求授權驗證檢查時,授權伺服器將會使用你帳戶的金鑰對組中的私密金鑰簽發一個授權驗證的回應.一旦the LVL接收到回應時,將會使用你嵌入在程式中的公開金鑰進行驗證授權簽章.
嵌入你軟體授權的公開金鑰在你的程式中:
2. 在帳號首頁,點入” Edit profile”的連結
3. 在”Edit Profile”網頁中,找到"Licensing"頁框,你的公開金鑰就揭露在"Public key"文字框.
4. 將它複製並放入程式中,如下:
public class MainActivity extends Activity { private static final String BASE64_PUBLIC_KEY = " MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi04GX9R9siXDTZrRBHPs3GDGMlR+bNFfynRQGdjMmISzjZpqlcC2SdxHAPJCZPIVVB7eeVCOUQDaTxwd82HBHNuvUvDdlDwAOE2kUnZb7lltNdB3MeBztXbxK/z7l7quGGnMT7/mIwqJ2WeOV79gYntPw+b0TNiugTRLzZ8wkRJa9kKu3p6t9oIpeUzmZvb3aRZgnT2M879TAiXuPUZKoLVMPhHLOQGNG0pnXmkaoDH6ok0War1ZuM/U0CahhbnLkjLekBrc8BWwBLl6dY32oET16L+dteK3ZNvix3pjiCrUm2kidoQm+nBM+LxQaRRZ4Febzcy0e3dlVeUJVqz0mQIDAQAB "; //truncated for this example ... } |
六、呼叫LicenseChecker的 onDestroy()方法結束IPC的連結
在主活動(Main Activity)的onDestroy() 方法中呼叫LicenseChecker的 onDestroy()方法來結束IPC的連結,避免耗費資源,以及避免使用者重新執行程式時將會造成重複執行多個IPC或產生衝突,同時在你更改程式內文之前清除the LVL的狀態, LicenseChecker的 onDestroy()方法會將Android Market程式的ILicensingService所開啟的所有IPC結束並移除所有在本地執行本項驗證的服務和操作的參數值.其方法如下:
@Override protected void onDestroy() { super.onDestroy(); mChecker.onDestroy(); ... } |
陸、實作設備的限制器
在某些情況下,你可能想將你的一次軟體授權,限制其實機被授權使用的數量,這種授權策略可以防止使用者將被授權的程式進行移植到其他多個實機上使用(當使用者在這些實機上使用相同的帳號ID進行認證時),它可以方止使用者透過其他個人所提供的帳號資訊來連結”分享”驗證程式.
The LVL提供DeviceLimiter interface設備限制器介面並支援對每一個設備的認證,可以宣告單一方法allowDeviceAccess(),當一個LicenseValidator認證有效因子操作授權伺服器所傳回來的回應訊息時, allowDeviceAccess()方法會被呼叫,並略過使用者ID字串去截取回應訊息.
如果你不想支援設備使用的限制,不須要做任何動作, LicenseChecker類別會自動使用預設的實作呼叫NullDeviceLimiter類別,其allowDeviceAccess()方法將回傳一個授權驗證給所有的認證通過的使用者和設備.
Google並不建議對每一台設備進行限制,因為如此將會導致你必須服務和管理所有使用者和使用設備的連結網路結構,而且它將導致非預期的結果,當使用者合法購買軟體在其他不同的設備上使用時,卻被認證系統拒絕而無法使用..
柒、設定測試環境
Android Market發佈商網站提供組態工具, 可以在你的程式發佈之前讓你可以和其他人測試授權驗證, 在你完成授權驗證程式的實作之後,你可以使用發佈商網站工具來測試你程式中的授權策略,並且可以操作不同的授權回應情形和錯誤條件.
授權驗證的測試環境主要的部分包括:
一、一個”測試回應”組態在你的發佈商帳號,讓你設定靜態的授權回應訊息,當伺服器處理一個上傳在發佈商帳號裏的程式, 經由使用者簽入到發佈商帳號或測試帳號時,進行授權檢查並傳送回應訊息.
二、你已將程式上傳(不論是否已經發佈)時,你可以將測試帳號作選擇性的設定,當進行檢查授權程式時可以收到靜態的測試回應訊息.
三、為你的程式提供一個執行期的環境,包括Android Market程式或Google APIs Add-On,在使用者簽入發佈商帳號或任一個測試帳號.
設定測試環境包含以下步驟:
一、設定靜態測試回應訊息,讓授權伺服器傳回使用
二、如有必要時設定測試帳號
三、簽入模擬器(Google APIs Add-On, API 8 (release 2) or higher)或實機,在你啟始授權檢查之前.
簽入模擬器的方法如下:
一、開啟模擬器上的”設定”點入”帳戶與同步處理”
二、按下新增帳號,選取新增一個"Google"帳號(使用登入已存在的帳號)
三、按”下一步”簽入,輸入使用者名稱及密碼(必須是在發佈商帳號中註冊的發佈商帳號或測試帳號)
四、按下”登入”,系統即登入你的帳號
在你登入之後,即可進行程式授權驗證的測試(如果你已經完成全部LVL整合的步驟).當你的程式啟始授權檢查時,它將會收到在發佈商帳號中設定的靜態測試回應訊息.
要注意,如果你使用模擬器進行測試,每次重新啟動模擬器時,如果你清除資料,你必須重新登入發佈商帳號或測試帳號,
Note that, if you are using an emulator, you will need to sign in to the publisher account or test account each time you wipe data when restarting the emulator.
Figure 8. Example of setting up a Google account on a device or emulator.
捌、亂碼化你的程式
要確保你程式的安全,特別是付費軟體使用授權機制或客製化拘束式保護者,亂碼化你的程式碼是非常重要的.它可以讓惡意的使用者在對程式進行反編譯位元組數碼時,增加很多的困難(通常他們會設法將授權檢查的程式碼移除後再重新編譯程式)
有許多專對Android applications應用的程式亂碼化工具可以使用,包括ProGuard,它也提供程式最佳化的功能.尤其當你使用Android Market Licensing時,強烈建議使用ProGuard或類似軟體將你的程式進行亂碼化.
ProGuard網址: http://proguard.sourceforge.net/
Android Application Licensing 網址:
http://developer.android.com/guide/publishing/licensing.html
Android Application Licensing 網址:
http://developer.android.com/guide/publishing/licensing.html