Steps:
1. 把 Requirements 都下載安裝好
2. 建立 Cordova Android Project
如果 Cordova projects 放置的位置與 Android App projects 是不同的目錄的話,test_cordova 可以改成與 android app project 相同名稱,這樣會比較好知道 cordova project 是對應到哪個 android project,此外 com.example.hello 也可以改成跟 android app 一樣。
cordova create test_cordova com.example.hello HelloWorld cordova platform add android cordova build
在 build 之前可以視情況加入需要的 plugins,例如:
cordova plugin add cordova-plugin-device cordova plugin add cordova-plugin-x-toast
3. 建立 Android App Project
用預設的即可,有一個 Empty Activity (MainActivity)。
4. 安裝 Cordova Project 環境到 Android Project
Compile Cordova Lib
參考 Android WebViews - Apache Cordova 步驟 1~3,把 cordova-x.x.x.jar 複製到 /libs 之後,編輯 app/build.gradle,加上:
compile files('libs/cordova-x.x.x.jar')
Example:
dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' compile files('libs/cordova-5.2.2.jar') }
複製依存檔案 (左邊是 Cordova project 的 path,右邊是 Android project 的 path)
www folder
platforms/android/assets/www -> src/main/assets/www
plugins (com/example/hello 以外的目錄,安裝 plugins 多出來的那些)
platforms/android/src/plugin_folder -> src/main/java/
config.xml
platforms/android/res/xml/config.xml -> src/main/res/xml/
然後 sync 一下 Gradle 情報。
5. 建立基本運作 Activity
把 Cordova Webview 嵌入 Android Native App 的基本作業到第四步驟就完成了,接下來可以建立基本運作的 Activity,來測試看看是不是正常運作。
建立以下兩個 Empty Activity: TestCordovaActivity, TestCordovaWithLayoutActivity,然後編輯 java 及 layout 如下:
TestCordovaActivity
public class TestCordovaActivity extends CordovaActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.init(); // Load your application launchUrl = "file:///android_asset/www/index.html"; loadUrl(launchUrl); } } @Override public void onDestroy() { ViewGroup viewGroup = (ViewGroup)this.findViewById(android.R.id.content); SystemWebView webView = (SystemWebView) viewGroup.getChildAt(0); viewGroup.removeView(webView); webView.removeAllViews(); super.onDestroy(); }
TestCordovaWithLayoutActivity
public class TestCordovaWithLayoutActivity extends CordovaActivity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_cordova_with_layout); super.init(); // Load your application launchUrl = "file:///android_asset/www/index2.html"; loadUrl(launchUrl); } @Override protected CordovaWebView makeWebView() { SystemWebView webView = (SystemWebView)findViewById(R.id.cordovaWebView); return new CordovaWebViewImpl(new SystemWebViewEngine(webView)); } @Override protected void createViews() { // Why are we setting a constant as the ID? This should be investigated /* appView.getView().setId(100); appView.getView().setLayoutParams(new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); setContentView(appView.getView()); */ if (preferences.contains("BackgroundColor")) { int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK); // Background of activity: appView.getView().setBackgroundColor(backgroundColor); } appView.getView().requestFocusFromTouch(); } @Override public void onDestroy() { SystemWebView webView = (SystemWebView)findViewById(R.id.cordovaWebView); ((ViewGroup)webView.getParent()).removeView(webView); webView.removeAllViews(); // If we called webView.destory(), we will get 'mWebViewCore is null' error. //webView.destroy(); super.onDestroy(); } }
activity_test_cordova_with_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.fandratec.fssfordksh.TestCordovaWithLayoutActivity"> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:background="#FF0000" android:textColor="#FFFFFF" android:gravity="center" android:text="This is native text view" /> <org.apache.cordova.engine.SystemWebView android:id="@+id/cordovaWebView" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
MainActivity
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void startCordovaActivity(View view) { Intent intent = new Intent(this, TestCordovaActivity.class); startActivity(intent); } public void startCordovaActivityWithLayout(View view) { Intent intent = new Intent(this, TestCordovaWithLayoutActivity.class); startActivity(intent); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.fandratec.fssfordksh.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" android:id="@+id/textView"/> <Button android:text="Start Cordova Activity Without Layout" android:onClick="startCordovaActivity" android:layout_width="200dp" android:layout_height="100dp" android:id="@+id/button" android:layout_below="@+id/textView" android:layout_alignParentStart="true"/> <Button android:text="Start Cordova Activity With Layout" android:onClick="startCordovaActivityWithLayout" android:layout_width="200dp" android:layout_height="100dp" android:layout_below="@+id/button" android:layout_alignParentStart="true"/> </RelativeLayout>
以上都弄好後,就可以 run 了。
6. 延伸
如果這個 Android App 要連線到 Internet 或是取得 GPS 座標,記得在 AndroidManifest.xml 加入權限需求宣告,如果沒加上的話會出現錯誤。(例如 loadUrl(REMOTE_URL) 就會直接獲得 "Application 錯誤")
<manifest> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> </manifest>
另外,現在版本的 Cordova project 預設啟用 whitelist 機制,想從 CordovaWebView 連到local (/assets/www) 外的內容並在其中呈現,得在 config.xml 加上設定,要不然會另外呼叫預設瀏覽器:
<widget> <allow-navigation href="https://YOUR.SITE/*" /> </widget>