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关键字给替换掉.. 然后其他的和原来操作一样

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值