如何破解uniapp写的应用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何破解uniapp写的应用相关的知识,希望对你有一定的参考价值。

最近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

三、创建一个 Uniapp 案例 (TCP-Plugin)
1、 开发者中心创建一个应用:https://dev.dcloud.net.cn/app/index?type=0

2、 点击应用名称进入应用,选择 离线打包Key管理 ,输入如下信息:

签名证书获取:

3、 点击保存会生成 appkey,后面要用到:4、 启动 HbuilderX,左下角登录自己的账户,新建一个和刚刚同名的项目的默认模板项目,查看 manifest.json AppID 是否云端 APPID 对应:

以上 uniapp demo 算是创建完成!

四、Android 原生插件开发
一、导入已下载好的离线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"

]

]

五、HbuilderX 生成本地打包 TCP-Plugin
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 生成本地打包资源:

六、离线打包apk并进行真机调试
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、测试,手机或者虚拟设备连接以后,点击运行进行测试:

七、打包生成原生插件 aar
八、HbuilderX 引入TCP-Socket 打包的 aar 插件:
1、目录结构以及 package.json 编写如下:
2、manifest.json 选择本地插件:

九、制作自定义调试基座

打包自定义基座成功如下:

十、HbuilderX 真机调试测试插件
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.

解决方法如下:

完结~~, 撒花~~
参考技术A 思路:
未登录:

生成一对RSA公钥私钥,公钥事先放在前端中,省去获取后端公钥的过程(防止被拦截,无法判断是否是后端传来的公钥)
用户未登陆时,通过公钥加密账号信息发送至后端,这样即便被窃取也无法得知内容
后端返回登陆生成的token,refresh token需要进行加密,理想办法是前端生成一对RSA公钥私钥,公钥发给后端加密,但是前端加密一般使用的node-rsa过大,微信小程序基本一引用就超出限制,uniapp压缩代码,分段都没用,所以放弃
前端将账号密码通过默认规则拼接成新字符串并MD5加密,作为对称加密密钥和账号传给后端,并加密token,refresh token返回。(token刷新问题可查看解决token刷新问题​​​​​​​)
登录后:

依旧生成一对RSA公钥私钥,公钥事先放在前端中,私钥存后端
前端通过对称加密AES加密数据,token,refresh token。将密钥通过准备好的RSA公钥加密,添加到请求头部
后端收到请求通过私钥解密头部,获得密钥解密数据
后端返回数据通过前端传的密钥AES加密返回。
实现加密解密:
对称加密AES使用crypto-js,非对称加密RSA使用jsencrypt

使用npm安装:

初始化

引入crypto-js

jsencrypt需要用到window变量,小程序不支持,解决办法有很多,这里直接下载jsencrypt.zip-小程序文档类资源-CSDN下载

然后引入使用就可以了

AES.js

uniapp蓝牙连接+打印

参考技术A 项目需求,做了低耗蓝牙打印功能,总结下如何实现功能的。下面是需要的api,刚开始写的时候有点多绕来绕去还是有点头疼哈哈,这个有个很大的问题就是不支持蓝牙版本4.0以下的版本。需要兼容另找其他办法。对于版本低的就会出现一些莫名其妙的问题。
1.uni.openBluetoothAdapter 初始化蓝牙模块
2.uni.onBluetoothDeviceFound 监听寻找到新设备的事件
3.uni.getBluetoothAdapterState 获取本机蓝牙适配器状态
4.uni.stopBluetoothDevicesDiscovery 停止搜寻附近的蓝牙设备
5.uni.createBLEConnection 初始化蓝牙连接
6.uni.getBLEDeviceServices 获取蓝牙设备服务
7.uni.getBLEDeviceCharacteristics 获取蓝牙设备某个服务中所有特征值(characteristic)
8.uni.writeBLECharacteristicValue 向低功耗蓝牙设备特征值中写入二进制数据
9.uni.startBluetoothDevicesDiscovery 开始搜寻附近的蓝牙设备

首先需要初始化蓝牙模块,如果没有初始化后面都不会在执行。然后再搜索周围设备。再把搜索到的设备存入数组,方便渲染。

蓝牙连接的时间有时效性,2min中过后会自动断开,然后导致打印数据输入不了,所以我在需要打印的时候再进行对设备连接,这样做可以在其他页面上也可以使用打印功能,并成功保持连接。

最后是效果图以及打印输出的结果

以上是关于如何破解uniapp写的应用的主要内容,如果未能解决你的问题,请参考以下文章

uniapp如何创建一个安卓应用并打包发布apk

uniapp如何提交代码推送

易语言写程序如何防破解?

uniapp如何更新微信小程序登录接口

uniapp刷礼物效果

uniapp如何把云数据库的内容显示出来