赞
踩
最近uniapp 开发移动app项目遇到一个棘手问题,我想实现 TCPScoket 通信。我们知道 uniapp 开发基本用的是一些前端框架(如:vue, mpvue等)和一些 uni 自身 api。要想 uniapp 使用 Android 原生代码有以下三种常用方法:
一: 使用 plus.android.importClass() 调用安卓的类进行原生代码编写,但是经测试效果很不理想,速度很慢!
二:开发原生 Android 插件,运行速度快,但需要一定的安卓开发经验,难度较高。
三:购买其他开发者开发的原生插件,但是一般价格不低。
综上所述,我们必须学会自己开发原生插件!
1、Android Studio 开发工具。 下载地址:https://developer.android.google.cn/studio/ 安装教程:https://blog.csdn.net/weixin_43883917/article/details/108942788
2、离线SDK下载(下载最新版)。 下载地址: https://nativesupport.dcloud.net.cn/AppDocs/download/android
3、保证 HbuilderX 也是最新版
4、签名证书。 生成方法:https://blog.csdn.net/weixin_58605808/article/details/117387435
1、 开发者中心创建一个应用:https://dev.dcloud.net.cn/app/index?type=0
2、 点击应用名称进入应用,选择 离线打包Key管理 ,输入如下信息:
签名证书获取:
3、 点击保存会生成 appkey,后面要用到:4、 启动 HbuilderX,左下角登录自己的账户,新建一个和刚刚同名的项目的默认模板项目,查看 manifest.json AppID 是否云端 APPID 对应:
以上 uniapp demo 算是创建完成!
一、导入已下载好的离线SDK中的原生插件开发框架项目,UniPlugin-Hello-AS
二、切换成 project模式, 项目结构如下:
三、把我们刚才申请的appkey填写到 app/src/main/AndroidManifest.xml
中,因为开发的是安卓,所以appkey填安卓的:
四、把我们的签名证书放到app目录下,博主的签名证书名叫 uniapp.keystore
五、配置签名证书,在 app/build.gradle
的 signingConfigs
选项中:
六、右键 UniPlugin-Hello-AS,创建 Module
七、填写插件模块信息:
八、配置 TCP-Socket/build.gradle
,复制官方案例 uniplugin_module/build.gradle
apply plugin: 'com.android.library' android { compileSdkVersion 29 defaultConfig { minSdkVersion 16 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } repositories { flatDir { dirs 'libs' } } dependencies { compileOnly fileTree(dir: 'libs', include: ['*.jar']) compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar']) compileOnly 'androidx.recyclerview:recyclerview:1.0.0' compileOnly 'androidx.legacy:legacy-support-v4:1.0.0' compileOnly 'androidx.appcompat:appcompat:1.0.0' implementation 'com.alibaba:fastjson:1.1.46.android' implementation 'com.facebook.fresco:fresco:1.13.0' /*implementation 'com.android.support:appcompat-v7:28.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'*/ }
九、删除不必要的官方案例,让项目更加简洁(可选):
十、在TCP-Socket 模块下的 com/example/tcp/socket 创建类TcpModule
十一、TCP Scocket 通信功能实现,代码如下:
package com.example.tcp.socket; import com.alibaba.fastjson.JSONObject; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import io.dcloud.feature.uniapp.annotation.UniJSMethod; import io.dcloud.feature.uniapp.bridge.UniJSCallback; import io.dcloud.feature.uniapp.common.UniModule; public class TcpModule extends UniModule { int port = 6666; Socket socket = null; OutputStreamWriter outputStream = null; InputStreamReader inputStream = null; @UniJSMethod public void send(final JSONObject json, final UniJSCallback callback) { new Thread(new Runnable() { @Override public void run() { String ip = json.getString("ip"); String userId = json.getString("code"); JSONObject res = new JSONObject(); // 建立与服务器的连接 try { socket = new Socket(ip, port); socket.setSoTimeout(1500); //建立连接后获取输入输出流 outputStream = new OutputStreamWriter(socket.getOutputStream()); inputStream = new InputStreamReader(socket.getInputStream()); } catch (Exception e) { try { socket.close(); } catch (IOException ioException) { ioException.printStackTrace(); } e.printStackTrace(); res.put("code", 400); res.put("data", "系统异常, 请重启APP!"); callback.invoke(res); } BufferedReader socketReader = new BufferedReader((inputStream)); BufferedWriter bufferedWriter = new BufferedWriter(outputStream); PrintWriter socketWriter = new PrintWriter(bufferedWriter, true); socketWriter.println(userId); try { String s = socketReader.readLine(); res.put("code", 200); res.put("data", s); // 这里关闭连接, 不然回调以后,程序就不执行了,不能再 finally 里面关闭连接 socket.close(); callback.invoke(res); } catch (IOException e) { res.put("code", 400); res.put("data", "系统异常, 请重启APP!"); callback.invoke(res); } } }).start(); } }
注意:Android4.0 以后不允许在主线程进行网络连接,否则会出现 android.os.NetworkOnMainThreadException。因此,必须另起一个线程进行网络连接方面的操作。
十二、注册插件,在 app/src/main/assets/dcloud_uniplugins.json
文件中写入,如下:
{
"nativePlugins": [
{
"plugins": [
{
"type": "module",
"name": "TCP-Socket",
"class": "com.example.tcp.socket.TcpModule"
}
]
}
]
}
1、引入原生插件方式如下:
const TCP = uni.requireNativePlugin("TCP-Socket");
index.vue 代码编写如下:
<template> <view class="content"> <image class="logo" src="/static/logo.png"></image> <view class="text-area"> <text class="title">{{title}}</text> </view> <view> <button @click="clickBtn">点击发送消息</button> </view> </view> </template> <script> const TCP = uni.requireNativePlugin("TCP-Socket"); export default { data() { return { title: 'TCP-Socket 插件测试' } }, onLoad() { }, methods: { clickBtn(){ TCP.send({ ip: '192.168.0.100', // 服务器ip code: 'd92863370904331f8a19cc116719bcd1' // 需要发送的数据 }, e => { // 回调函数 uni.showToast({ title: '响应数据:' + JSON.stringify(e), icon: 'none' }); }) } } } </script> <style> (...省略) </style>
2、HbuilderX 生成本地打包资源:
1、把生成的本地打包资源复制到 UniPlugin-Hello-AS
项目的 app/src/main/assets/apps
目录下:
2、配置 appid,在 UniPlugin-Hello-AS
项目的 app/src/main/assets/data/dcloud_control.xml
中配置:
3、在 UniPlugin-Hello-AS
项目的 app/build.gradle 中对 TCP-Socket 插件引用:
4、测试,手机或者虚拟设备连接以后,点击运行进行测试:
1、目录结构以及 package.json 编写如下:
2、manifest.json 选择本地插件:
打包自定义基座成功如下:
1、选择自定义调试基座:
注意:如果出现已经制作自定义调试基座,但是没有运行基座选择这一选项的情况。请重新进行自定义基座打包,直到出现运行基座选择为止!
2、选择运行到 Android App 基座进行真机调试:
测试成功!
1、 [JS Framework] 当前运行的基座不包含原生插件[xxxx],请在manifest中配置该插件,重新制作包括该原生插件的自定义运行基座。
问题分析:
1、 package.json 配置编写错误 (仔细进行对照).
2、 是否在manifest中配置 (这种睿智操作一般不会犯)
3、 原生插件是否使用自定义基座 (大部分是这个原因)
4、 自己开发原生插件是否有错误,未成功打包到基座 (原因是这个的概率很小,因为在 Android Studio 离线打包的时候我们调试通过了,说明插件没有问题。)
2、Android Studio 问题:Gradle task list not built during sync.Building the task list can impact Gradlesync performance on large projects.
解决方法如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。