<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [toc] # [Android Plugin Development Guide](http://cordova.apache.org/docs/en/latest/guide/platforms/android/plugin.html) 首先你要去看看[插件開發指南](插件開發指南.md),以便對插件開發有個總體的結構認識。本節繼續演示示例echo插件,該插件從Cordova webview通信到本機平臺并返回。有關另一個示例,另請參閱 [CordovaPlugin.java](https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java) 中的注釋。 Android插件基于 Cordova-Android ,它是使用帶有原生橋接(*native bridge*)的 Android WebView構建的。 Android插件的原生部分包含至少一個繼承(extends) `CordovaPlugin` 類并覆蓋其中的一個 `execute` 方法。 # 插件類映射 該插件的JavaScript接口使用 `cordova.exec` 方法,如下所示: ~~~ exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]); ~~~ 這將從WebView 向Android 本地端封送一個請求,有效地調用 `service`類上的 `action`方法,并在 `args`數組中傳遞附加參數。 無論是將插件作為Java 文件還是作為自己的 jar 文件分發,都必須在Cordova-Android 應用程序的 `res/xml/config.xml` 文件中指定插件。有關如何使用 `plugin.xml` 文件注入此 `feature`元素的詳細信息,請參閱應用程序插件: ~~~ <feature name="<service_name>"> <param name="android-package" value="<full_name_including_namespace>" /> </feature> ~~~ `service_name` 與 `JavaScript exec` 調用中使用的名稱匹配。該值是Java類的完全限定名稱空間標識符。否則,插件可能會編譯但仍然無法訪問Cordova。 # 插件初始化和生命周期 在每個 `WebView` 的生命周期中創建一個插件對象實例。除非首先通過JavaScript調用引用插件,否則不會實例化插件,除非在 `config.xml` 中將帶有`onload` `name`屬性的設置為“true”。例如: ~~~ <feature name="Echo"> <param name="android-package" value="<full_name_including_namespace>" /> <param name="onload" value="true" /> </feature> ~~~ 插件應該使用 `initialize` 方法初始化它們的啟動邏輯。 ~~~ @Override public void initialize(CordovaInterface cordova, CordovaWebView webView) { super.initialize(cordova, webView); // your init code here } ~~~ 插件還可以訪問Android生命周期事件,并可以通過j集成其中一個提供的方法(`onResume`,`onDestroy`等)來處理它們。具有長時間運行請求,后臺活動(如媒體播放,偵聽器或內部狀態)的插件應實現`onReset()`方法。它在`WebView` 導航到新頁面或刷新時執行,這會重新加載JavaScript。 # 編寫一個Android Java插件 JavaScript調用會觸發對本機端的插件請求,相應的Java插件會在config.xml文件中正確映射,但最終的Android Java插件類是什么樣的? 使用JavaScript的`exec`函數調度到插件的任何內容都會傳遞到插件類的 `execute`方法中。大多數`execute`實現看起來像這樣: ~~~ @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { if ("beep".equals(action)) { this.beep(args.getLong(0)); callbackContext.success(); return true; } return false; // Returning false results in a "MethodNotFound" error. } ~~~ JavaScript `exec`函數的`action` 參數對應于一個私有類方法,可以用可選參數進行分派。 當捕獲異常并返回錯誤時,為了清晰起見,返回到JavaScript的錯誤盡可能地匹配Java的異常名是非常重要的。 # 線程 插件的JavaScript不會在 `WebView` 接口的主線程中運行;相反,它和 `execute`方法一樣運行在 `WebCore` 線程上。如果您需要與用戶界面交互,您應該使用 [Activity's runOnUiThread](http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)) 方法,如下所示: ~~~ @Override public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException { if ("beep".equals(action)) { final long duration = args.getLong(0); cordova.getActivity().runOnUiThread(new Runnable() { public void run() { ... callbackContext.success(); // Thread-safe. } }); return true; } return false; } ~~~ 如果您不需要在UI線程上運行,但也不希望阻止WebCore線程,您應該使用從 `Cordova.getthreadpool()` 獲得的Cordova `ExecutorService`執行代碼,如下所示: ~~~ @Override public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException { if ("beep".equals(action)) { final long duration = args.getLong(0); cordova.getThreadPool().execute(new Runnable() { public void run() { ... callbackContext.success(); // Thread-safe. } }); return true; } return false; } ~~~ # 添加依賴庫 如果你的Android插件有額外的依賴項,它們必須在插件的`plugin.xml` 中以兩種方式中的一種列出。 首選方法是使用 `<framework />` 標記(有關詳細信息,請參閱[插件規范](http://cordova.apache.org/docs/en/latest/plugin_ref/spec.html#framework))。以這種方式指定庫允許通過Gradle的[依賴關系管理](https://docs.gradle.org/current/userguide/dependency_management.html)邏輯來解析它們。這允許多個插件使用諸如*gson*,*android-support-v4* 和 *google-play-services* 之類的常用庫而不會發生沖突。 第二個選項是使用 `<lib-file />` 標記指定 *jar* 文件的位置(有關詳細信息,請參閱[插件規范](http://cordova.apache.org/docs/en/latest/plugin_ref/spec.html#framework))。只有當您確信沒有其他插件依賴于您正在引用的庫時(例如,如果庫是特定于您的插件的話),才應該使用這種方法。 例如: ~~~ <lib-file src="src/android/PaySDK/libs/alipaySdk-20170725.jar" /> ~~~ 該jar包會被自動復制到 `platforms>android>libs` 下面! 否則,如果另一個插件添加了相同的庫,則可能會導致插件用戶出現構建錯誤。值得注意的是,Cordova應用程序開發人員不一定是原生開發人員,因此原生構建錯誤尤其令人沮喪。 # Echo Android插件的例子 要匹配Application Plugins中描述的JavaScript接口的echo功能,請使用 `plugin.xml` 將 `feature`規范注入原生平臺的`config.xml`文件: ~~~ <platform name="android"> <config-file target="config.xml" parent="/*"> <feature name="Echo"> <param name="android-package" value="org.apache.cordova.plugin.Echo"/> </feature> </config-file> <source-file src="src/android/Echo.java" target-dir="src/org/apache/cordova/plugin" /> </platform> ~~~ 然后將以下內容添加到`src/android/Echo.java` 文件中: ~~~ package org.apache.cordova.plugin; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CallbackContext; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; /** * This class echoes a string called from JavaScript. */ public class Echo extends CordovaPlugin { @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { if (action.equals("echo")) { String message = args.getString(0); this.echo(message, callbackContext); return true; } return false; } private void echo(String message, CallbackContext callbackContext) { if (message != null && message.length() > 0) { callbackContext.success(message); } else { callbackContext.error("Expected one non-empty string argument."); } } } ~~~ 文件頂部的必要導入擴展了`CordovaPlugin` 的類,它的 `execute()` 方法覆蓋了 `exec()` 接收消息。`execute()` 方法首先測試`action`的值,在這種情況下,只有一個有效的`echo`值。任何其他操作返回 `false` 并導致`INVALID_ACTION` 錯誤,這會轉換為在JavaScript端調用的錯誤回調。 接下來,該方法使用 `args`對象的 `getString` 方法檢索echo字符串,指定傳遞給方法的第一個參數。將值傳遞給私有echo方法后,將對其進行參數檢查,以確保它不是`null`或空字符串,在這種情況下,`callbackContext.error()` 調用JavaScript的錯誤回調。如果各種檢查通過,`callbackContext.success()` 將原始 `message` 字符串傳遞回JavaScript成功回調作為參數。 # Android集成 Android具有 [Intent](http://developer.android.com/reference/android/content/Intent.html) 系統,允許進程相互通信。插件可以訪問 `CordovaInterface` 對象,該對象可以訪問運行應用程序的[Android Activity](http://developer.android.com/reference/android/app/Activity.html)。這是啟動新[Android Intent](http://developer.android.com/reference/android/content/Intent.html)所需的[Context](http://developer.android.com/reference/android/content/Context.html)*上下文*。 CordovaInterface允許插件為結果啟動[Activity](http://developer.android.com/reference/android/app/Activity.html),并為 [Intent](http://developer.android.com/reference/android/content/Intent.html) 返回應用程序時設置回調插件。 從Cordova 2.0開始,插件就不能直接訪問[Context](http://developer.android.com/reference/android/content/Context.html),并且不贊成使用遺留的`ctx` 成員。所有`ctx` 方法都存在于[Context](http://developer.android.com/reference/android/content/Context.html)中,因此 `getContext()`和`getActivity()` 都可以返回所需的對象。 # Android權限 直到最近,Android權限一直是在安裝時而不是運行時處理的。需要在使用這些權限的應用程序上聲明這些權限,并且需要將這些權限添加到 Android Manifest 中。這可以通過 `config.xml` 來實現 將這些權限注入到 `AndroidManifest.xml` 文件中。下面的示例使用 聯系人權限。 ~~~ <config-file target="AndroidManifest.xml" parent="/*"> <uses-permission android:name="android.permission.READ_CONTACTS" /> </config-file> ~~~ # 運行時權限(Cordova-Android 5.0.0+) Android 6.0 "Marshmallow" 引入了一種新的權限模型,用戶可以根據需要打開和關閉權限。這意味著應用程序必須處理這些權限更改,以確保不變更,這是Cordova-Android 5.0.0版本的重點。 需要在運行時處理的權限可以在此處的[Android Developer文檔](http://developer.android.com/guide/topics/security/permissions.html#perm-groups)中找到。 就插件而言,可以通過調用權限方法來請求權限;簽名如下: ~~~ cordova.requestPermission(CordovaPlugin plugin, int requestCode, String permission); ~~~ 為了減少冗長,標準的做法是把它賦給一個局部靜態變量: ~~~ public static final String READ = Manifest.permission.READ_CONTACTS; ~~~ 下面這樣定義 `requestCode` 也是標準做法: ~~~ public static final int SEARCH_REQ_CODE = 0; ~~~ 然后,在 `exec`方法中,應檢查權限: ~~~ if(cordova.hasPermission(READ)) { search(executeArgs); } else { getReadPermission(SEARCH_REQ_CODE); } ~~~ 在這種情況下,我們只調用 `requestPermission`: ~~~ protected void getReadPermission(int requestCode) { cordova.requestPermission(this, requestCode, READ); } ~~~ 這將調用活動并導致出現提示,要求獲得權限。一旦用戶擁有權限,就必須使用 `onRequestPermissionResult` 方法處理結果,每個插件都應覆蓋該方法。下面是一個例子: ```java public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException { for(int r:grantResults) { if(r == PackageManager.PERMISSION_DENIED) { this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR)); return; } } switch(requestCode) { case SEARCH_REQ_CODE: search(executeArgs); break; case SAVE_REQ_CODE: save(executeArgs); break; case REMOVE_REQ_CODE: remove(executeArgs); break; } } ``` 上面的`switch`語句將從提示符返回,并且根據傳入的`requestCode`,將調用相應的方法。應該注意的是,如果未正確處理執行,則可以堆疊權限提示,并且應該避免這種情況。 除了要求獲得單個權限的權限之外,還可以通過定義權限數組來請求整個組的權限,就像使用 Geolocation 插件所做的那樣: ~~~ String [] permissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }; ~~~ 然后在請求權限時,需要做的就是: ~~~ cordova.requestPermissions(this, 0, permissions); ~~~ 這會請求數組中指定的權限。提供可公開訪問的權限數組是個好主意,因為這可以被使用你的插件作為依賴項的插件使用,盡管這不是必需的。 # 調試Android插件 雖然推薦使用Android studio,但可以使用Eclipse 或Android Studio 進行Android調試。由于Cordova-Android 目前用作庫項目,并且支持插件作為源代碼,因此可以像在本機Android應用程序中一樣調試Cordova應用程序中的Java代碼。 # 啟動其他 Activities 如果您的插件啟動將Cordova活動推送到后臺的活動,則需要特別注意。如果設備內存不足,Android OS將在后臺銷毀活動。在這種情況下,`CordovaPlugin`實例也將被銷毀。如果您的插件正在等待它所啟動的Activity的結果,那么當Cordova [Activity](http://developer.android.com/reference/android/app/Activity.html) 返回到前臺并獲得結果時,將創建插件的新實例。但是,插件的狀態不會自動保存或恢復,插件的 `CallbackContext` 將丟失。 `CordovaPlugin` 可以通過兩種方法來處理這種情況: ```java /** * Called when the Activity is being destroyed (e.g. if a plugin calls out to an * external Activity and the OS kills the CordovaActivity in the background). * The plugin should save its state in this method only if it is awaiting the * result of an external Activity and needs to preserve some information so as * to handle that result; onRestoreStateForActivityResult() will only be called * if the plugin is the recipient of an Activity result * * @return Bundle containing the state of the plugin or null if state does not * need to be saved */ public Bundle onSaveInstanceState() {} /** * Called when a plugin is the recipient of an Activity result after the * CordovaActivity has been destroyed. The Bundle will be the same as the one * the plugin returned in onSaveInstanceState() * * @param state Bundle containing the state of the plugin * @param callbackContext Replacement Context to return the plugin result to */ public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {} ``` 重要的是要注意,只有在插件為結果啟動Activity 時才應使用上述方法,并且只應恢復處理該Activity 結果所需的狀態。插件的狀態將不會被恢復,除非在使用 `CordovaInterface`的`startActivityForResult()` 方法獲得插件請求的Activity結果并且在后臺 操作系統銷毀Cordova活動時。 作為 `onRestoreStateForActivityResult()` 的一部分,您的插件將被傳遞一個替換 CallbackContext。重要的是要意識到這個CallbackContext 與使用 Activity銷毀的CallbackContext 不同。原始回調丟失,并且不會在javascript應用程序中觸發。相反,此替換CallbackContext 將返回結果作為應用程序恢復時觸發的[`resume`](http://cordova.apache.org/docs/en/latest/cordova/events/events.html#resume)事件的一部分。[`resume`](http://cordova.apache.org/docs/en/latest/cordova/events/events.html#resume)事件的有效負載遵循以下結構: ~~~ { action: "resume", pendingResult: { pluginServiceName: string, pluginStatus: string, 00000000000000000000 result: any } } ~~~ `pluginServiceName` 將匹配 `plugin.xml` 中的[name元素](http://cordova.apache.org/docs/en/latest/plugin_ref/spec.html#name)。 `pluginStatus` 是一個String,描述傳遞給CallbackContext的 PluginResult 的狀態。有關與插件狀態對應的String值,請參閱`PluginResult.java` `result` 是插件傳遞給`CallbackContext`的任何結果(例如 String,number,JSON object等) 此 [`resume`](http://cordova.apache.org/docs/en/latest/cordova/events/events.html#resume) 有效負載將傳遞給javascript應用程序為 `resume`事件注冊的任何回調中。這意味著結果*直接*進入Cordova應用程序;您的插件將無法在應用程序收到之前使用javascript處理結果。因此,您應該努力使本機代碼返回的結果盡可能完整,并且在 launching activities(啟動活動)時不依賴于任何javascript回調。 請務必告知Cordova應用程序如何解釋他們在 [`resume`](http://cordova.apache.org/docs/en/latest/cordova/events/events.html#resume) 事件中收到的結果。 Cordova應用程序需要維護自己的狀態,并記住他們提出的請求以及必要時提供的參數。但是,您仍應清楚地傳達 `pluginStatus` 值的含義以及作為插件API的一部分在`resume` 字段中返回的數據類型。 啟動活動的完整事件序列如下: 1. Cordova應用程序調用您的插件 2. 您的插件會為結果啟動一個Activity 3. Android操作系統會破壞Cordova Activity和您的插件實例 `onSaveInstanceState()`被調用 4. 用戶與您的活動進行交互,活動完成 5. 重新創建Cordova活動并接收活動結果 `onRestoreStateForActivityResult()`被調用 6. 調用 `onActivityResult()` 并且您的插件將結果傳遞給新的CallbackContext 7. Cordova應用程序觸發并接收 `resume` 事件 Android 提供了一個開發人員設置,用于在低內存上調試 活動銷毀(Activity destruction)。在您的設備或模擬器上的Developer Options菜單中啟用“Don't keep activities”設置,以模擬低內存場景。如果您的插件啟動了外部活動,您應該始終啟用該設置進行一些測試,以確保正確地處理低內存場景。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看