weex學習之路及遇到的坑和解決方法

這是個人在學習weex中遇到的坑,以及解決方法,歡迎共同交流

weex簡介

js作爲連接原生控件與視圖層紐帶 ,代替了以往使用的java、oc、swift直接調用原生控件 、這樣生成的ui層依舊是原生的、和 html毫無關係,至於那些div,image只不過是名字和html標籤一樣的組件而已,也沒有了dome對象的存在,因爲實際 開發的環境不是瀏覽器,而是基於原生,

初始化:

 

  • 1,初始環境:安裝node.js以及mpm
  • 2,npm install weex-toolkit -g

全局安裝weex-tooklkit

在命令環境註冊一個weex命令

  • 3,進入到需要部署的文件目錄

weex create awesome-app

命令執行完成,當前名錄的awesome-app文件夾裏就存在一個空Weex Vue.js項目

 

開發:

 

  1. 進入創建的文件夾,安裝依賴,
    1. cd awesome-app
    2. npm install
    3. npm start
  2. 工具會 啓動一個本地的web服務,監聽8081端口。打開http://localhost:8081查看頁面在web下的渲染效果。
    1. 源代碼在src/目錄中,你可以像一個普通Vue.js項目一樣進行開發
    2. 可以打開http://localhost:8081/preview.html開啓預覽頁面,他會把web端頁面放在一個iframe中渲染,右側二維碼可以用Weex palyround app掃描預覽;

運行和編譯

 

 

安裝weexpack:

初始環境:安裝node.js以及mpm

$ cnpm install -g weexpack

或者 在 clone 的 weexpack 根目錄下執行

$ cnpm install

 

創建 weexpack工程

weexpack create appNmae (工程名)

 

cd appName

npm install 初始化依賴

 

 

 

安裝應用模板 生成 android 或者 ios 工程

  • android模板

weexpack platform add android

執行完成後會在platforms文件夾下生成android文件目錄

  • ios工程模板

weexpack platform add ios

執行完成後會在platforms文件夾下生成ios文件目錄

weex platform add android

 

 

 

開發完成之後weex run android

打包android工程

 

 

然後用android stodio 打開工程編譯

 

坑1:

 

applicationVariants.all { variant ->

variant.outputs.each { output ->

def outputFile = output.outputFile

if (outputFile != null && outputFile.name.equals('app-debug.apk')) {

def fileName = outputFile.name.replace("app-debug.apk", "weex-app.apk")

output.outputFile = new File(outputFile.parent, fileName)

}

}

}

替換爲

applicationVariants.all { variant ->

variant.outputs.all { output ->

def fileName = "${variant.versionName}_release.apk"

def outFile = output.outputFile

// if (outputFile != null && outputFile.name.equals('app-debug.apk')) {

// def fileName = outputFile.name.replace("app-debug.apk", "weex-app.apk")

// outputoutputFile = fileName

// }

if (outFile != null && outFile.name.endsWith('.apk')) {

outputFileName = fileName // output.outputFile 改爲 outputFileName

}

}

}

 

 

坑2

Error:Execution failed for task ':uikit:javaPreCompileDebug'. > Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the annotationProcessor configuration. - compiler-4.0.0-RC0.jar (com.github.bumptech.glide:compiler:4.0.0-RC0) - auto-service-1.0-rc3.jar (com.google.auto.service:auto-service:1.0-rc3) Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior. Note that this option is deprecated and will be removed in the future. See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.

 

解決方法: 

在app的build.gradle中添加如下部分:

android { compileSdkVersion 26 buildToolsVersion '26.0.2' defaultConfig { applicationId "com.example.app" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" //添加部分 javaCompileOptions { annotationProcessorOptions { includeCompileClasspath true } } } }

 

坑三:不顯示本地文件

 

weex不顯示本地文件,

可以直接寫絕對路徑 ip+端口號/src/存放圖片文件夾/圖片名稱

 

然後在安卓和ios分別的解決方法是:

Android 的實現方法

圖片存儲的目錄

res/drawable-hdpi

下面會提到,爲何要存儲到這裏

引用方法

<img src="local:///test" style="width: 300; height: 300;">

不需要加圖片的文件名後綴

注意:是三個斜槓,不是兩個,否則會報錯

E/weex: Local src format is invalid.

如果你是在google play上上架。建議mdpi,hdpi,xhdpi,xxhdpi每一種都放一套(ldpi就算了,基本看不到),因爲google play會根據不同的手機density來打不同的apk包(舉個栗子,如果是hdpi的機器,下載下來的就只有hdpi的資源) 如果是在國內的市場話。建議只放一套(h或者xhpdi),因爲國內市場是沒有上面那種機制的,放多套資源會導致安裝包變得很大。 此外: Android在沒有找到相應dpi的圖片時,會用其他density的圖片進行縮放處理。因此會損失一些性能和內存(作爲縮放的buffer使用)

參考 Android 開發中 drawable 有必要放多套分辨率的圖片資源嗎?

iOS 的實現方法

圖片存儲目錄

main bundle

引用方法

<img src="local://test.png" style="width: 300; height: 300;">

我這裏直接報 domain error, 而不是 no resource found 說明並沒有走最新的 SDK 代碼流程。

最終在官方文檔 Path (英) | Weex 的相對路徑部分找到了解決方法。

即使用相對路徑即可!

xcode 最傻逼的地方是,需要手動將圖片拖動到項目的 resource 目錄。 需要自動添加的方案!!!

先手動在 resource 目錄新建一個 images 目錄,然後,不斷往這個目錄裏新增圖片文件即可。

 

同步解決(感覺不夠完美)

圖片的同步

npm run copy:xx 解決

package.json

"scripts": { "build": "webpack", "dev": "npm run build && webpack --watch", "copy:android": "mkdir -p platforms/android/app/src/main/assets/dist/; cp dist/index.weex.js platforms/android/app/src/main/assets/dist/index.js; cp src/images/*.* platforms/android/app/src/main/res/drawable-hdpi/", "copy:ios": "mkdir -p platforms/ios/bundlejs/ && cp dist/index.weex.js platforms/ios/bundlejs/index.js && cp src/images/*.* platforms/ios/images/", "copy": "npm run copy:android && npm run copy:ios", "serve": "serve -p 1337", "test": "echo \"Error: no test specified\" && exit 1" },

實現代碼

src/mixins/index.js

// 獲取圖片在三端上不同的路徑 // e.g. 圖片文件名是 test.jpg, 轉換得到的圖片地址爲 // - H5 : http: //localhost:1337/src/images/test.jpg // - Android : local:///test // - iOS : ../images/test.jpg get_img_path(img_name) { let platform = weex.config.env.platform let img_path = '' if (platform == 'Web') { img_path = `http://localhost:1337/src/images/${img_name}` } else if (platform == 'android') { // android 不需要後綴 img_name = img_name.substr(0, img_name.lastIndexOf('.')); img_path = `local:///${img_name}` } else { img_path = `../images/${img_name}` } return img_path }

使用方法

<image style="width: 120px; height: 120px;" :src="get_img_path('test.png')"></image>

 

坑4:

頁面跳轉問題

https://blog.csdn.net/blog_lee/article/details/79820130詳情可參考

 

新增uril.js,在需要的頁面調用代碼如下

export function getEntryUrl(name) {

//判斷當前的環境,適配web端

if (weex.config.env.platform === "Web") {

// return './' + name + '.html'

} else {

let arr = weex.config.bundleUrl.split('/');

arr.pop();

arr.push(name + '.js');

console.log(arr.join('/'))

return "local://" + arr.join('/');

}

}

 

 

使用方法:

navigator.push({

// url: "./detail.html",

url: getEntryUrl("login"),

animated: "true"

})

Android相關代碼

  • 創建一個Activity,如下圖所示位置以及代碼

這裏寫圖片描述

package com.weex.app.util; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import com.taobao.weex.IWXRenderListener; import com.taobao.weex.WXSDKInstance; import com.taobao.weex.common.WXRenderStrategy; import com.taobao.weex.devtools.common.LogUtil; import com.weex.app.R; import java.util.HashMap; import java.util.Map; /** * Created by lee on 29/03/2018. */ public class Network extends AppCompatActivity implements IWXRenderListener { private WXSDKInstance mWXSDKInstance; private FrameLayout mContainer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_network); mContainer = (FrameLayout) findViewById(R.id.container); mWXSDKInstance = new WXSDKInstance(this); mWXSDKInstance.registerRenderListener(this); String RenderPageUrl = ""; if (getIntent().getData() != null) { String navUrl = getIntent().getData().toString(); if (null != navUrl) { LogUtil.e(navUrl); RenderPageUrl = navUrl; } else { LogUtil.e("a is null"); } } else { LogUtil.e("get data is null"); } Map<String, Object> options = new HashMap<>(); options.put(WXSDKInstance.BUNDLE_URL, RenderPageUrl); mWXSDKInstance.renderByUrl("WXSample", RenderPageUrl, options, null, WXRenderStrategy.APPEND_ONCE); } @Override protected void onStart() { super.onStart(); if (mWXSDKInstance != null) { mWXSDKInstance.onActivityStart(); } } @Override protected void onResume() { super.onResume(); if (mWXSDKInstance != null) { mWXSDKInstance.onActivityResume(); } } @Override protected void onPause() { super.onPause(); if (mWXSDKInstance != null) { mWXSDKInstance.onActivityPause(); } } @Override protected void onStop() { super.onStop(); if (mWXSDKInstance != null) { mWXSDKInstance.onActivityStop(); } } @Override protected void onDestroy() { super.onDestroy(); if (mWXSDKInstance != null) { mWXSDKInstance.onActivityDestroy(); } } @Override public void onViewCreated(WXSDKInstance instance, View view) { if (view.getParent() != null) { ((ViewGroup) view.getParent()).removeView(view); } mContainer.addView(view); } @Override public void onRenderSuccess(WXSDKInstance instance, int width, int height) { } @Override public void onRefreshSuccess(WXSDKInstance instance, int width, int height) { } @Override public void onException(WXSDKInstance instance, String errCode, String msg) {

  • 創建Activity佈局文件 

這裏寫圖片描述

<?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:id="@+id/activity_network" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"></FrameLayout> </RelativeLayout>

  •  
  • 修改manifest.xml-添加攔截器

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.weex.app"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/> <uses-feature android:name="android.hardware.camera"/> <uses-feature android:name="android.hardware.camera.autofocus"/> <application android:name="com.weex.app.WXApplication" android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" tools:overrideLibrary="com.taobao.android.dexposed" tools:replace="android:allowBackup"> <activity android:name="com.weex.app.SplashActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/app_name" android:screenOrientation="portrait" android:theme="@style/FullscreenTheme"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name="com.weex.app.WXPageActivity" android:label="@string/app_name" android:screenOrientation="portrait"> </activity> <activity android:name=".util.Network"> <intent-filter> <action android:name="com.taobao.android.intent.action.WEEX" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="com.taobao.android.intent.category.WEEX" /> <action android:name="android.intent.action.VIEW" /> <data android:scheme="http" /> <data android:scheme="https" /> <data android:scheme="file" /> <data android:scheme="network" /> </intent-filter> </activity> <activity android:name="com.journeyapps.barcodescanner.CaptureActivity" android:screenOrientation="portrait" tools:replace="screenOrientation"/> </application> </manifest>

 

坑5

android7 權限問題:

 

https://blog.csdn.net/jupiterxx/article/details/80026909

你的項目就可以用 weex run android運行在安卓手機上了... 

網上好多說需要找到本地資源文件夾下的地址即可跳轉.. 在android中.. 確實發現assets文件夾下有這些界面的js文件.. 

 

只要用 file://assets/dist/在安卓中找到這個文件跳轉就可以了.. 然後再次發現是無效的.. 但是發現跳轉http和https在手機上是有效的.. 那麼也就是說隱式調用沒有攔截到這file這個請求..

 

但是明明在android項目的manifast裏是已經在攔截file的.. 最後發現確實file是攔截不到的.. 其他什麼關鍵字都可以.. 那麼怎麼辦呢.. 最後我只能在地址前面加上別的關鍵字local 但是讓隱式攔截local關鍵字.. 最後再activity裏再把local給去掉 用file地址去渲染..

 

最終獲取三端對應跳轉地址的方法 (注意安卓中前面添加了local是爲了給攔截)

  1. getJumpBaseUrl(toUrl) {
  2.  
  3. var bundleUrl = weex.config.bundleUrl;
  4.  
  5. var isnav = true
  6. bundleUrl = new String(bundleUrl);
  7. var nativeBase;
  8. var native;
  9. var isAndroidAssets = bundleUrl.indexOf('file://assets/') >= 0;
  10. var isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0;
  11. if (isAndroidAssets) {
  12. nativeBase = "local://" + 'file://assets/dist/';
  13. native = nativeBase + toUrl + ".js";
  14. } else if (isiOSAssets) {
  15. nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);
  16. native = nativeBase + toUrl + ".js";
  17. } else {
  18. var host = 'localhost:8081';
  19. var matches = /\/\/([^\/]+?)\//.exec(bundleUrl);
  20. if (matches && matches.length >= 2) {
  21. host = matches[1];
  22. }
  23.  
  24. //此處需注意一下,tabbar 用的直接是jsbundle 的路徑,但是navigator是直接跳轉到新頁面上的.
  25. if (typeof window === 'object') {
  26. nativeBase = 'http://' + host + '/';
  27. } else {
  28. nativeBase = 'http://' + host + '/';
  29. }
  30.  
  31. native = nativeBase + toUrl + ".html";
  32. }
  33. return native;
  34. }

android manifest 中攔截local

  1. <activity
  2. android:name="com.weex.app.WXPageActivity"
  3. android:label="@string/app_name"
  4. android:screenOrientation="portrait"
  5.  
  6. >
  7. <intent-filter>
  8. <action android:name="android.intent.action.VIEW"/>
  9. <action android:name="com.alibaba.weex.protocol.openurl"/>
  10.  
  11. <category android:name="android.intent.category.DEFAULT"/>
  12. <category android:name="com.taobao.android.intent.category.WEEX"/>
  13.  
  14. <data android:scheme="http"/>
  15. <data android:scheme="https"/>
  16. <data android:scheme="local"/>
  17. </intent-filter>
  18.  
  19.  
  20.  
  21. </activity>

android java code中把local頭給去掉 拿file地址去渲染

 

把local關鍵字給替換掉.. 然後其他的和原來操作一樣

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章