parent
a2a8310573
commit
3b219cdea2
|
|
@ -10,8 +10,8 @@ android {
|
|||
applicationId "com.ycgis.macall.personalcenter"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 30
|
||||
versionCode 2506051
|
||||
versionName "3.1.20250605.01"
|
||||
versionCode 2507041
|
||||
versionName "3.1.20250704.01"
|
||||
// versionCode 2000000
|
||||
// versionName "2.0.202403221"
|
||||
|
||||
|
|
@ -101,6 +101,11 @@ dependencies {
|
|||
//Zxing 二维码识别
|
||||
implementation 'com.github.jenly1314:zxing-lite:2.1.1'
|
||||
|
||||
//蓝牙打印机相关
|
||||
implementation files('libs\\4.0.0-release.aar')
|
||||
implementation files('libs\\image-1.8.9.aar')
|
||||
implementation files('libs\\LPAPI-2019-11-20-R.jar')
|
||||
|
||||
// implementation('com.github.gzu-liyujiang:Android_CN_OAID:4.2.5.1') {
|
||||
// // 如果使用了移动安全联盟SDK,共存的话需排除掉本项目依赖的华为/荣耀官方广告标识服务SDK,因为移动安全联盟SDK也依赖了华为/荣耀的SDK
|
||||
// // 如果华为官方广告标识服务SDK下载失败或编译报错的话,可考虑在 build.gradle 中增加以下配置:
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -88,7 +88,7 @@
|
|||
-keep public class com.ycgis.macall.personalcenter.p.request.UploadProgressResponsBody{*;}
|
||||
|
||||
-keep public class com.ycgis.macall.personalcenter.m.adapterbean.**{*;}
|
||||
-keep public class com.ycgis.macall.personalcenter.m.datamodel.PrintModel{*;}
|
||||
-keep public class com.ycgis.macall.personalcenter.m.datamodel.**{*;}
|
||||
-keep public class com.ycgis.macall.personalcenter.m.event.MessageEvent{*;}
|
||||
-keep public class com.ycgis.macall.personalcenter.m.enumbean.**{*;}
|
||||
-keep public class com.ycgis.macall.personalcenter.m.provider.**{*;}
|
||||
|
|
@ -306,3 +306,20 @@ long consumerIndex;
|
|||
public <fields>;
|
||||
}
|
||||
-keepattributes Signature
|
||||
|
||||
|
||||
#蓝牙打印机的配置
|
||||
-keep public class com.gengcon.www.jcprintersdk.**{*;}
|
||||
-keep public class com.niimbot.canvas.image.**{*; }
|
||||
-keep public class com.dothantech.**{*;}
|
||||
-keep public class zpSDK.zpSDK.**{*;}
|
||||
-keep public class com.snbc.sdk.**{*;}
|
||||
-keep public class android_serialport_api.**{*;}
|
||||
-dontwarn com.gengcon.www.jcprintersdk.**
|
||||
-dontwarn com.jingchen.jcimagesdk.**
|
||||
-dontwarn com.niimbot.canvas.image.**
|
||||
-dontwarn com.dothantech.**
|
||||
-dontwarn zpSDK.zpSDK.**
|
||||
-dontwarn com.snbc.sdk.**
|
||||
-dontwarn android_serialport_api.**
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"versionCode": 2506051,
|
||||
"versionName": "3.1.20250605.01",
|
||||
"versionCode": 2507041,
|
||||
"versionName": "3.1.20250704.01",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -47,7 +47,10 @@
|
|||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.NewPersonalCenter"
|
||||
tools:targetApi="n">
|
||||
<activity android:name=".v.activity.BluetoothActivity"/>
|
||||
<activity android:name=".v.activity.BluetoothActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustUnspecified|stateHidden|stateAlwaysHidden|adjustPan"/>
|
||||
<activity
|
||||
android:name=".v.activity.applyfo.PersonnelReviewActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<button class="buttonClass" id="buttonId22" onclick="callJS()">JS弹框</button>
|
||||
|
||||
<p>
|
||||
<button class="buttonClass" id="buttonId101" onclick="linkBluetooth()">链接蓝牙</button>
|
||||
<button class="buttonClass" id="buttonId101" onclick="linkBluetooth()">连接蓝牙</button>
|
||||
|
||||
<p>
|
||||
<button class="buttonClass" id="buttonId102" onclick="printContentssss()">打印内容</button>
|
||||
|
|
@ -60,14 +60,14 @@
|
|||
<script>
|
||||
|
||||
function linkBluetooth() {
|
||||
callByAndroid.openBluetooth();
|
||||
callByAndroid.openJCBluetooth();
|
||||
}
|
||||
|
||||
function printContentssss() {
|
||||
<!-- alert(111111111)-->
|
||||
|
||||
var json = '[{"content":"文字内容","printType":1},{"content":"二维码内容","printType":2}]';
|
||||
callByAndroid.printContentsJSON(json);
|
||||
var json = '[{"pageWidth":70,"pageHeight":50,"printData":[{"content":"文字内容","printType":1,"contentWidth":70,"contentHeight:":90},{"content":"二维码内容","printType":2,"zoomLevel":5,"contentWidth":35,"contentHeight:":35}]},{"pageWidth":70,"pageHeight":50,"printData":[{"content":"文字内容","printType":1,"contentWidth":70,"contentHeight:":90},{"content":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAACdFJREFUeF7tnc1uFEcQgKsXIxEJInDkA5IjecnNvAA3mwtP4AM34+BIzgEpL5CAkxdAyiFImNi55eAn4GJz4wXinGAXYYkDwlhRJJBib0e19sAwTHdXT/9M906NhEDsTE9X1ddV1T39I4CvTmtAdFp6Fh4YgI5DwAAwAB3XQMfFZw/AAHRcAx0Xnz0AA5CnBi6uDeZ6R7A8rr0czbUihegNhYAXbx72t1p5v4eXZucBxob/b3QXhLjlQX4/RUgYAsjd0dne+uGD/tBPoXFKyQqA6dXBXQB5L45qGrwFQRBi62Cjv97g6VYeyQaAS6vPdwTAYitasn6puJcLBFkAkHzLrwUkDwiSB+Di6mCxB3LHuhEm8MAIxPXDjf5uAlVRViF5AKZvPx+AgNosf+bLKViYvzAWDv8d+9rbfwdP9v5Vv1bC8ODRlX7setm8L2kAvvpucEtKuVknEBp87cYMXJ09ZyOv93tf/3MEP2+/Avy7/ko7FCQNgK71/7h0uXXjFwZH49/5/WW9/RP3AskCoGv9C/Pn4fsbM95bs0uBvz1+rQwHQoiVVAeLkgVA1+3784f0wqrOC0iA3bcbV667ABbq2SQAKA/rSpCLuv5+iq2/MA7mAnv775WhQAoYCimHotd7cixhmEIPoTUAPhrdbmQPXT9CkOL11/57+GX7Fb1qpyOHI4AnbcEQHQDs1wuQd5uO6qXo/knJoAkLCcORECuxQYgGQNMWX9Zbyu6fFAZMEIx/j9ttjAKALqMn6eT0pqVrl2Dp2kWbR6Lfu/30ELafvnV7b8SPSsEB8DmOn3L8LyxunQdoUQnvDYICMH372ab1d/sx/fVDv79++3UrQ742zdnUHbTPfcJCEAwAq8+3RTY8BX+gsntHclCn9JQTwHJ9b96vrT7gxyGYguGZY1gcSblMhkHKrYNH36zYgEi9NwgAZLcvYSh6Yr08SqbKF+Znz8FPS5epcrV6n2o8oPp1EGWlgxDGE3gHgP75tl4gFQA59ABMPQHVkDC1wYT4vOwdgOnV51Lb/Az93UkAQP1dQN2KT+Y6yh1V/jPWKerurLjuc96hVwBMcZ8yJq5qDTl0AQvw1V1BvRtHCMSR3NTlBhQd2sQ/bwCYXD+14l0GAA1HgcBnKPAGgLb1a76Jo8BlYlVTvtEDpPoNoNricJZQ3WAQNgI5JT5k8ypXbgoH1MZE8QReADC1fh2xjcYKKJLlcI+me3cydF7fHUbRfHkBLwDoY78+7jEA6v69rnfgywt4AUCZ+ROmQzEAagC0+QBBtxQn6AyA7kMPZSoUA6Af4dPp10cYcAZAaUAioQyAHgC9F3AfIvYAgGrePm3ochznpExnoSfFb3q7R+5SxviVuQCxkemq6w6AYuRvNCX6PkesvOk8w4J0vSzXMOAEgK5iBxtXnMrO0E5Bq6xKtFsFQJmgBPx8GVTLCReu6mpTEu1gIYABiEeMekyAlmupaurkpkNVKp5a83lTKF27AaCY8uXqlvIxS7yahvK2DEA8Gzq9iQFwUl/+DzMA+dvQSQIGwEl9+T/MAORvQycJGAAn9eX/MAOQuQ1Phs1hoen+gQxAxgB8Or2r2cgdA5ApAPUTPO0hYAAyBUA5X9JykQcDkCEApoUyNit9GIDMAKCs97OZ2csAZASAaZ0EimJjfLyfAcgEANOCjrEYlvGfAcjJ+KYVvg1X9bAHyAACY9LX0PjsASbE+C5bwLEHSBgC3xl/nagMQKIAUDJ+TPpcD45gABIEgJTxO8T9ssgMQGIAmDZxKKrrunCjKIcBSAwASsbvkvRVxWUAEgKAYnzbkT6TeAyASUORfo+R8XMvIJIxbV8TK+NnAGwtE+H+mBk/AxDBoDaviJ3xZw9A0339ca/9B49fjzeFbuMkUBUU2sOgTh8KvZMp7j2IW9B+djkuxQ+yNrAJAOWDFlI5FRSVTTF+jJ3MJxqAukMWinOB2zwihnL8SwzjI4gTDYCulYV2rSq3Tzn6BSGNFa4mFgCKi40NgfYs4BIxMc8vnkgAzCdvf9Q2tjY8Myj0Ra1TTONPdAhAhWN2qzxytWTxGC43RY800QCgcAiBaov1aosP2UOgGD9W0leVeyJDQFVIStaNz4ToIVDeHSsM1YW5TgCAglMMUSjIV3JIyfjxnbHjfhmEzgCgjXc1TcMVghQz/k57gEJ4ajZehIQmPQTqO5qMbPrurXTKAzSFwHZQJuWkr5NJYF2rse0mrt2Ygauz54wNMCfjT3w30GQt227iwvwF7THzlESzzYyfc4AaDdhAgI+rksMcMn4GQOMSKK1X1U3MJeNnAAwxQZkR1zxXuHJqxu/arTSFs6a/d7IXoFMW1aBFNxFBMH1vaGuYlwIFA6DICzCbRxhcr5SN3/legMkTUL8mqsqJ8ZXRFVD2ABoN2vYQqkW1OcZPBSNNAPDMP5D3qkK0kUg1hSAH46cbAhICoIDQpZtIbY1t3KeWy37X0XL9naaFqxYsLsyfB/yA0tZF6SamnvRVdYd5DspVvVzPZ3ICQLVWLgXl6rqJqQ3zUhqK6ttFkgCkomAVBLnE/TIYN+8PajlxPaLXzQOsDeZ6R7K2ZqkouQpBKvWitPriHl1Icz2i1wkArKBqs4S284CygosewslcwvM2uk/iXlX8B8d1gSicMwCqDRNSCQOFBRGClBac2pB15/eXtaOdrvHfCwC6dfMpTKWyUXSK9+rcv2v89wKALgyk5gVSNLCpTqrWj8+5xn9vACg3MNJMzDAJzr9rVgSPleM2AFTo1zkHwIJ0YSDkSp5JhsQ0c8lH6/fmAbAgnRfgUGCPqn7Sqp/W7xUA0yZKKXUL7c0R9wnTjGVfrd8rACYvgL8zBGaQTMb3Ffu95gBlsaZvP9sEIW6pROVwoIbAZHzfu4969wAfEkLDsSmcGH4KQbE7mnZqm4ct5+vQ89ILqBZsygeK+zEk4OSRXEfozA5df4fNJBZfu45XaxQEgLEnGB+WLHdMSkLj4+fj+dkvshynN8lX9zu2+L/338P207ekx0MZP0gIKEtE3WGzeAZhKP4gEJNyFa59b/+dcWr6JzLj8XJCrBxu9HdD6SKYBygqbAtBKEGzKzdQzI8WAj7zBEewXDeBNDvDRKmwv4EeU3WDe4AqCOJIbgqARVPFOvl7gxNFXfUUFYCisjhsPJJymUE41YiEoeiJ9TcP+1uuBrV9vhUAyvnBmWNY7CQMEoYgxNbBRn/d1mg+728VgGp4gCOYOyNgDv9fjkYLPgVttSzRG467XAJeHEsYhszqbeVMBgDbivP9fjTAAPjRY7alMADZms5PxRkAP3rMthQGIFvT+ak4A+BHj9mWwgBkazo/FWcA/Ogx21L+ByHRYvkl6tFhAAAAAElFTkSuQmCC","printType":3,"contentWidth:":90,"contentHeight:":90}]}]';
|
||||
callByAndroid.printJCContentsJSON(json);
|
||||
}
|
||||
|
||||
function showNetError() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,467 @@
|
|||
package com.ycgis.macall.jcBluetooth;
|
||||
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import com.gengcon.www.jcprintersdk.JCPrintApi;
|
||||
import com.gengcon.www.jcprintersdk.bean.PaperInfo;
|
||||
import com.gengcon.www.jcprintersdk.callback.Callback;
|
||||
import com.gengcon.www.jcprintersdk.callback.PrintCallback;
|
||||
import com.rs.macall.androidx.basemodel.utils.BitMapUtils;
|
||||
import com.rs.macall.androidx.basemodel.utils.StringUtil;
|
||||
import com.ycgis.macall.personalcenter.m.datamodel.PrintData;
|
||||
import com.ycgis.macall.personalcenter.m.datamodel.PrintModel;
|
||||
import com.ycgis.macall.personalcenter.p.app.RuanseeApplication;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 打印工具类
|
||||
*
|
||||
* @author zhangbin
|
||||
*/
|
||||
public class PrintUtil {
|
||||
|
||||
public static final Map<Integer, String> ERROR_MESSAGES = new HashMap<>();
|
||||
private static final int PERMISSION_REQUEST_CODE = 1524;
|
||||
|
||||
static {
|
||||
ERROR_MESSAGES.put(-1, "打印机未连接");
|
||||
ERROR_MESSAGES.put(1, "盒盖打开");
|
||||
ERROR_MESSAGES.put(2, "缺纸");
|
||||
ERROR_MESSAGES.put(3, "电量不足");
|
||||
ERROR_MESSAGES.put(4, "电池异常");
|
||||
ERROR_MESSAGES.put(5, "手动停止");
|
||||
ERROR_MESSAGES.put(6, "数据错误");
|
||||
ERROR_MESSAGES.put(7, "温度过高");
|
||||
ERROR_MESSAGES.put(8, "出纸异常");
|
||||
ERROR_MESSAGES.put(9, "正在打印");
|
||||
ERROR_MESSAGES.put(10, "没有检测到打印头");
|
||||
ERROR_MESSAGES.put(11, "环境温度过低");
|
||||
ERROR_MESSAGES.put(12, "打印头未锁紧");
|
||||
ERROR_MESSAGES.put(13, "未检测到碳带");
|
||||
ERROR_MESSAGES.put(14, "不匹配的碳带");
|
||||
ERROR_MESSAGES.put(15, "用完的碳带");
|
||||
ERROR_MESSAGES.put(16, "不支持的纸张类型");
|
||||
ERROR_MESSAGES.put(17, "纸张类型设置失败");
|
||||
ERROR_MESSAGES.put(18, "打印模式设置失败");
|
||||
ERROR_MESSAGES.put(19, "设置浓度失败");
|
||||
ERROR_MESSAGES.put(20, "写入rfid失败");
|
||||
ERROR_MESSAGES.put(21, "边距设置失败");
|
||||
ERROR_MESSAGES.put(22, "通讯异常");
|
||||
ERROR_MESSAGES.put(23, "打印机连接断开");
|
||||
ERROR_MESSAGES.put(24, "画板参数错误");
|
||||
ERROR_MESSAGES.put(25, "旋转角度错误");
|
||||
ERROR_MESSAGES.put(26, "json参数错误");
|
||||
ERROR_MESSAGES.put(27, "出纸异常(B3S)");
|
||||
ERROR_MESSAGES.put(28, "检查纸张类型");
|
||||
ERROR_MESSAGES.put(29, "RFID标签未进行写入操作");
|
||||
ERROR_MESSAGES.put(30, "不支持浓度设置");
|
||||
ERROR_MESSAGES.put(31, "不支持的打印模式");
|
||||
}
|
||||
|
||||
|
||||
private static final String TAG = "PrintUtil";
|
||||
private static int mConnectedType = -1;
|
||||
/**
|
||||
* 单例实例,使用 volatile 保证多线程可见性和有序性
|
||||
*/
|
||||
private static volatile JCPrintApi api;
|
||||
|
||||
/**
|
||||
* 回调接口,用于处理打印机状态变化事件
|
||||
*/
|
||||
private static final Callback CALLBACK = new Callback() {
|
||||
private static final String TAG = "PrintUtil";
|
||||
|
||||
/**
|
||||
* 连接成功回调
|
||||
*
|
||||
* @param address 设备地址,蓝牙为蓝牙 MAC 地址,WIFI 为 IP 地址
|
||||
* @param type 连接类型,0 表示蓝牙连接,1 表示 WIFI 连接
|
||||
*/
|
||||
@Override
|
||||
public void onConnectSuccess(String address, int type) {
|
||||
mConnectedType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开连接回调
|
||||
* 当设备断开连接时,将调用此方法。
|
||||
*/
|
||||
@Override
|
||||
public void onDisConnect() {
|
||||
mConnectedType = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 电量变化回调
|
||||
* 当设备电量发生变化时,将调用此方法。
|
||||
*
|
||||
* @param powerLevel 电量等级,取值范围为 1 到 4,代表有 1 到 4 格电,满电是 4 格
|
||||
*/
|
||||
@Override
|
||||
public void onElectricityChange(int powerLevel) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 监测上盖状态变化回调
|
||||
* 当上盖状态发生变化时,将调用此方法。目前该回调仅支持 H10/D101/D110/D11/B21/B16/B32/Z401/B3S/B203/B1/B18 系列打印机。
|
||||
*
|
||||
* @param coverStatus 上盖状态,0 表示上盖打开,1 表示上盖关闭
|
||||
*/
|
||||
@Override
|
||||
public void onCoverStatus(int coverStatus) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 监测纸张状态变化
|
||||
* 当纸张状态发生变化时,将调用此方法。目前该回调仅支持H10/D101/D110/D11/B21/B16/B32/Z401/B203/B1/B18 系列打印机。
|
||||
*
|
||||
* @param paperStatus 0为不缺纸 1为缺纸
|
||||
*/
|
||||
@Override
|
||||
public void onPaperStatus(int paperStatus) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 监测标签rfid读取状态变化
|
||||
* 当标签rfid读取状态发生变化时,将调用此方法。
|
||||
*
|
||||
* @param rfidReadStatus 0为未读取到标签RFID 1为成功读取到标签RFID 目前该回调仅支持H10/D101/D110/D11/B21/B16/B32/Z401/B203/B1/B18 系列打印机。
|
||||
*/
|
||||
@Override
|
||||
public void onRfidReadStatus(int rfidReadStatus) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 监测碳带rfid读取状态变化
|
||||
* 当碳带rfid读取状态发生变化时,将调用此方法。
|
||||
*
|
||||
* @param ribbonRfidReadStatus 0为未读取到碳带RFID 1为成功读取到碳带RFID 目前该回调仅支持B18/B32/Z401/P1/P1S 系列打印机。
|
||||
*/
|
||||
@Override
|
||||
public void onRibbonRfidReadStatus(int ribbonRfidReadStatus) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 监测碳带状态变化
|
||||
* 当纸张状态发生变化时,将调用此方法
|
||||
*
|
||||
* @param ribbonStatus 0为无碳带 1为有碳带 目前该回调仅支持B18/B32/Z401/P1/P1S系列打印机。
|
||||
*/
|
||||
@Override
|
||||
public void onRibbonStatus(int ribbonStatus) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 固件异常回调,需要升级
|
||||
* 当设备连接成功但出现固件异常时,将调用此方法,表示需要进行固件升级。
|
||||
*/
|
||||
@Override
|
||||
public void onFirmErrors() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 获取 JCPrintApi 单例实例
|
||||
*
|
||||
* @return JCPrintApi 实例
|
||||
*/
|
||||
public static JCPrintApi getInstance() {
|
||||
// 双重检查锁定以确保只初始化一次实例
|
||||
if (api == null) {
|
||||
synchronized (PrintUtil.class) {
|
||||
if (api == null) {
|
||||
api = JCPrintApi.getInstance(CALLBACK);
|
||||
//api.init已废弃,使用initSdk替代,方法名含义更准确
|
||||
api.initSdk(RuanseeApplication.getApplication());
|
||||
//获取内置目录路径
|
||||
// File directory = MyApplication.getInstance().getFilesDir();
|
||||
//获取自定义字体路径
|
||||
// File customFontDirectory = new File(directory, "custom_font");
|
||||
// api.initDefaultImageLibrarySettings(customFontDirectory.getAbsolutePath(), "");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return api;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过打印机mac地址进行蓝牙连接开启打印机(同步)
|
||||
*
|
||||
* @param address 打印机地址
|
||||
* @return 成功与否
|
||||
*/
|
||||
public static int connectBluetoothPrinter(String address) {
|
||||
// 获取单例实例以确保线程安全
|
||||
JCPrintApi localApi = getInstance();
|
||||
//api.openPrinterByAddress(address),使用connectBluetoothPrinter替代,方法名含义更准确
|
||||
return localApi.connectBluetoothPrinter(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭打印机
|
||||
*/
|
||||
public static void close() {
|
||||
// 获取单例实例以确保线程安全
|
||||
JCPrintApi localApi = getInstance();
|
||||
localApi.close();
|
||||
}
|
||||
|
||||
|
||||
public static int getConnectedType() {
|
||||
return mConnectedType;
|
||||
}
|
||||
|
||||
public static void setConnectedType(int connectedType) {
|
||||
mConnectedType = connectedType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查打印机是否连接
|
||||
*
|
||||
* @return 连接状态代码
|
||||
*/
|
||||
public static int isConnection() {
|
||||
// 获取单例实例以确保线程安全
|
||||
JCPrintApi localApi = getInstance();
|
||||
return localApi.isConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印回调接口
|
||||
*/
|
||||
public interface PrintStatusCallback {
|
||||
void onProgress(int pageIndex, int quantityIndex);
|
||||
|
||||
void onError(int errorCode, int printState);
|
||||
|
||||
void onCancelJob(boolean isSuccess);
|
||||
|
||||
void onPrintComplete();
|
||||
}
|
||||
|
||||
|
||||
public static void startLabelPrintJob(int copies, int density, int labelType, int mode,
|
||||
Handler handler,
|
||||
List<String> jsonList, List<String> infoList, PrintStatusCallback callback) {
|
||||
// 打印参数校验
|
||||
if (isConnection() != 0) {
|
||||
handler.post(() -> callback.onError(-1, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化打印状态
|
||||
AtomicInteger generatedPages = new AtomicInteger(0);
|
||||
AtomicBoolean isError = new AtomicBoolean(false);
|
||||
AtomicBoolean isCancel = new AtomicBoolean(false);
|
||||
int pages = jsonList.size();
|
||||
// 设置打印总量
|
||||
getInstance().setTotalPrintQuantity(pages * copies);
|
||||
|
||||
// 启动打印任务
|
||||
getInstance().startPrintJob(density, labelType, mode, new PrintCallback() {
|
||||
@Override
|
||||
public void onProgress(int pageIndex, int quantityIndex, HashMap<String, Object> hashMap) {
|
||||
handler.post(() -> callback.onProgress(pageIndex, quantityIndex));
|
||||
if (pageIndex == pages && quantityIndex == copies) {
|
||||
getInstance().endPrintJob();
|
||||
handler.post(callback::onPrintComplete);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i) {
|
||||
//无需处理
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, int printState) {
|
||||
isError.set(true);
|
||||
handler.post(() -> callback.onError(errorCode, printState));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelJob(boolean success) {
|
||||
isCancel.set(success);
|
||||
handler.post(() -> callback.onCancelJob(success));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferFree(int pageIndex, int bufferSize) {
|
||||
if (isError.get() || isCancel.get() || pageIndex > pages) return;
|
||||
|
||||
Log.d(TAG, "测试:onBufferFree ");
|
||||
// 生成打印数据
|
||||
int commitSize = Math.min(pages - generatedPages.get(), bufferSize);
|
||||
List<String> subJson = jsonList.subList(generatedPages.get(), generatedPages.get() + commitSize);
|
||||
List<String> subInfo = infoList.subList(generatedPages.get(), generatedPages.get() + commitSize);
|
||||
getInstance().commitData(subJson, subInfo);
|
||||
generatedPages.addAndGet(commitSize);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 绘制打印内容
|
||||
*/
|
||||
public static boolean drawLabelJson(PrintModel printModel) {
|
||||
|
||||
/**
|
||||
* //-1失败,0成功
|
||||
* public int state = -1;
|
||||
*
|
||||
* //间隙⾼度(⿊标⾼度)(单位像素)
|
||||
* public int gapHeightPixel;
|
||||
*
|
||||
* //纸张⾼度(包含间隙)(单位像素)
|
||||
* public int totalHeightPixel;
|
||||
*
|
||||
* //纸张类型 :1:间隙纸; 2:⿊标纸; 3:连续纸; 4:定孔纸; 5:透明纸; 6:标牌;
|
||||
* public int paperType;
|
||||
*
|
||||
* //间隙⾼度(⿊标⾼度)(单位毫⽶)
|
||||
* public float gapHeight;
|
||||
*
|
||||
* //纸张⾼度(包含间隙)(单位毫⽶)
|
||||
* public float totalHeight;
|
||||
*
|
||||
* //纸张宽度(包含间隙)(单位像素)
|
||||
* public int paperWidthPixel;
|
||||
*
|
||||
* //纸张宽度(包含间隙)(单位毫⽶)
|
||||
* public float paperWidth;
|
||||
*
|
||||
* //尾巴⽅向1上2下3左4右(暂不⽀持)
|
||||
* public int direction;
|
||||
*
|
||||
* //尾巴⻓度(单位像素)
|
||||
* public int tailLengthPixel;
|
||||
* //尾巴⻓度(单位毫⽶)
|
||||
* public float tailLength
|
||||
*/
|
||||
List<PrintData> printData = printModel.getPrintData();
|
||||
if (printData == null) return false;
|
||||
|
||||
float width = printModel.getPageWidth();
|
||||
float height = printModel.getPageHeight();
|
||||
int orientation = 0;
|
||||
float marginX = 2.0F;
|
||||
float marginY = 2.0F;
|
||||
float rectangleWidth = width - marginX * 2;
|
||||
float rectangleHeight = height - marginY * 2;
|
||||
float fontSize = 6.0F;
|
||||
float offsetY = 0F;
|
||||
float offsetX = 0F;
|
||||
float lineWidth = 0.5F;
|
||||
float lineHeight = rectangleHeight / 5.0F;
|
||||
|
||||
PrintUtil.getInstance().drawEmptyLabel(width, height, orientation, new ArrayList<>());
|
||||
|
||||
//已经绘制的高度
|
||||
float yhzgd = 2f;
|
||||
for (int i = 0; i < printData.size(); i++) {
|
||||
PrintData data = printData.get(i);
|
||||
if (data == null) continue;
|
||||
if (data.getPrintType() == 1) {
|
||||
String content = data.getContent();
|
||||
if (StringUtil.isNullOrEmpty(content)) {
|
||||
continue;
|
||||
}
|
||||
fontSize = data.getTextSize();
|
||||
|
||||
// 绘制⽂本
|
||||
PrintUtil.getInstance().drawLabelText(marginX, yhzgd, rectangleWidth, rectangleHeight,
|
||||
content, "", fontSize, 0, 1, 0, 2, 0, 1, new boolean[]{true, false, false, false});
|
||||
float v = content.length() * fontSize + (marginX * 2);
|
||||
yhzgd += fontSize;
|
||||
if (v > width) {//如果换行了就再加一行的高度
|
||||
yhzgd = fontSize + 1f;
|
||||
}
|
||||
} else if (data.getPrintType() == 2) {//二维码
|
||||
float qrWidth = 10;
|
||||
int contentHeight = Math.max(data.getContentHeight(), data.getContentWidth());
|
||||
//页面可用高度
|
||||
float v = height - (yhzgd + 3f) - marginY * 2;
|
||||
if (contentHeight > v) {
|
||||
qrWidth = v;
|
||||
} else {
|
||||
qrWidth = contentHeight;
|
||||
}
|
||||
float v1 = rectangleWidth - qrWidth;
|
||||
float startX = 2f;
|
||||
if (v1>0){
|
||||
startX = v1/2 +marginX;
|
||||
}
|
||||
//绘制二维码
|
||||
PrintUtil.getInstance().drawLabelQrCode(startX, yhzgd + 3f,
|
||||
qrWidth, qrWidth, data.getContent(), 31, 0);
|
||||
yhzgd += 3f + qrWidth;
|
||||
} else if (data.getPrintType() == 3) {// 图片
|
||||
if (StringUtil.isNullOrEmpty(data.getContent()))continue;
|
||||
String base64 = data.getContent().replace("data:image/png;base64,", "");
|
||||
Bitmap bitmap = BitMapUtils.base64ToBitmap(base64);
|
||||
if (bitmap == null) continue;
|
||||
|
||||
int bitmapWidth = bitmap.getWidth();
|
||||
int bitmapHeight = bitmap.getHeight();
|
||||
|
||||
//页面可用高度
|
||||
float v = height - (yhzgd + 3f) - marginY * 2;
|
||||
|
||||
float imgWidth = 10;
|
||||
float imgHeight = 10;
|
||||
|
||||
// 如果图片本身就小于画布,直接返回原始尺寸
|
||||
if (bitmapWidth <= rectangleWidth && bitmapHeight <= v) {
|
||||
imgWidth = bitmapWidth;
|
||||
imgHeight = bitmapHeight;
|
||||
} else {
|
||||
// 计算宽高缩放比例
|
||||
float widthRatio = (float) rectangleWidth / bitmapWidth;
|
||||
float heightRatio = (float) v / bitmapHeight;
|
||||
|
||||
// 选择较小的缩放比例,以确保图片能完整显示在画布内
|
||||
float scaleRatio = Math.min(widthRatio, heightRatio);
|
||||
// 计算缩放后的新尺寸
|
||||
imgWidth = (bitmapWidth * scaleRatio);
|
||||
imgHeight = (bitmapHeight * scaleRatio);
|
||||
}
|
||||
|
||||
float v1 = rectangleWidth - imgWidth;
|
||||
float startX = 2f;
|
||||
if (v1>0){
|
||||
startX = v1/2 +marginX;
|
||||
}
|
||||
//绘制二维码
|
||||
PrintUtil.getInstance().drawLabelImage(base64, startX, yhzgd + 3f,
|
||||
imgWidth, imgHeight, 0, 1, 127);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.ycgis.macall.personalcenter.m.datamodel;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/6/27 9:43
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
public class PrintData {
|
||||
private String content;
|
||||
private int printType;
|
||||
private int contentWidth;
|
||||
private int contentHeight;
|
||||
|
||||
//文字大小
|
||||
private int textSize;
|
||||
|
||||
private int zoomLevel;
|
||||
|
||||
private int pageWidth;
|
||||
private int pageHeight;
|
||||
|
||||
public int getZoomLevel() {
|
||||
if (zoomLevel>32) return 32;
|
||||
return Math.max(zoomLevel, 1);
|
||||
}
|
||||
|
||||
public void setZoomLevel(int zoomLevel) {
|
||||
this.zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public int getPrintType() {
|
||||
return printType;
|
||||
}
|
||||
|
||||
public void setPrintType(int printType) {
|
||||
this.printType = printType;
|
||||
}
|
||||
|
||||
public int getContentWidth() {
|
||||
return contentWidth;
|
||||
}
|
||||
|
||||
public void setContentWidth(int contentWidth) {
|
||||
this.contentWidth = contentWidth;
|
||||
}
|
||||
|
||||
public int getContentHeight() {
|
||||
return contentHeight;
|
||||
}
|
||||
|
||||
public void setContentHeight(int contentHeight) {
|
||||
this.contentHeight = contentHeight;
|
||||
}
|
||||
|
||||
public int getPageWidth() {
|
||||
return pageWidth;
|
||||
}
|
||||
|
||||
public void setPageWidth(int pageWidth) {
|
||||
this.pageWidth = pageWidth;
|
||||
}
|
||||
|
||||
public int getPageHeight() {
|
||||
return pageHeight;
|
||||
}
|
||||
|
||||
public void setPageHeight(int pageHeight) {
|
||||
this.pageHeight = pageHeight;
|
||||
}
|
||||
|
||||
public int getTextSize() {
|
||||
return Math.max(textSize,6);
|
||||
}
|
||||
|
||||
public void setTextSize(int textSize) {
|
||||
this.textSize = textSize;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.ycgis.macall.personalcenter.m.datamodel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/5/29 16:56
|
||||
|
|
@ -7,73 +9,34 @@ package com.ycgis.macall.personalcenter.m.datamodel;
|
|||
* Describe:
|
||||
*/
|
||||
public class PrintModel {
|
||||
// "content":"文字内容",
|
||||
// * "printType":1
|
||||
|
||||
private String content;
|
||||
private int printType;
|
||||
private int contentWidth;
|
||||
private int contentHeight;
|
||||
private int pageHeight;
|
||||
private int pageWidth;
|
||||
private int zoomLevel;
|
||||
private float pageWidth;
|
||||
private float pageHeight;
|
||||
|
||||
public int getZoomLevel() {
|
||||
if (zoomLevel>32) return 32;
|
||||
return Math.max(zoomLevel, 1);
|
||||
private List<PrintData> printData;
|
||||
|
||||
|
||||
public float getPageWidth() {
|
||||
return pageWidth;
|
||||
}
|
||||
|
||||
public void setZoomLevel(int zoomLevel) {
|
||||
this.zoomLevel = zoomLevel;
|
||||
public void setPageWidth(float pageWidth) {
|
||||
this.pageWidth = pageWidth;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
public float getPageHeight() {
|
||||
return pageHeight;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public int getPrintType() {
|
||||
return printType;
|
||||
}
|
||||
|
||||
public void setPrintType(int printType) {
|
||||
this.printType = printType;
|
||||
}
|
||||
|
||||
public int getContentWidth() {
|
||||
return contentWidth;
|
||||
}
|
||||
|
||||
public void setContentWidth(int contentWidth) {
|
||||
this.contentWidth = contentWidth;
|
||||
}
|
||||
|
||||
public int getContentHeight() {
|
||||
return contentHeight;
|
||||
}
|
||||
|
||||
public void setContentHeight(int contentHeight) {
|
||||
this.contentHeight = contentHeight;
|
||||
}
|
||||
|
||||
public int getPageHeight() {
|
||||
if (pageHeight<100)return 100;
|
||||
return Math.min(pageHeight,2000);
|
||||
}
|
||||
|
||||
public void setPageHeight(int pageHeight) {
|
||||
public void setPageHeight(float pageHeight) {
|
||||
this.pageHeight = pageHeight;
|
||||
}
|
||||
|
||||
public int getPageWidth() {
|
||||
if (pageWidth<100)return 100;
|
||||
return Math.min(pageWidth,2000);
|
||||
public List<PrintData> getPrintData() {
|
||||
return printData;
|
||||
}
|
||||
|
||||
public void setPageWidth(int pageWidth) {
|
||||
this.pageWidth = pageWidth;
|
||||
public void setPrintData(List<PrintData> printData) {
|
||||
this.printData = printData;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class RuanseeApplication extends BaseApplication {
|
|||
AuthConfig config = AuthConfig.builder();
|
||||
config.setThemeColor(ContextCompat.getColor(getApplicationContext(), R.color.colorAccent));
|
||||
config.setAuthTypes(types);
|
||||
AuthSDK.init("55b161aefd464849b48986a1073d5622", this, config);
|
||||
AuthSDK.init(getAppCache().getSysmCode(), this, config);
|
||||
// AuthMarkManager.setShowAuthMark(true);
|
||||
//应用中心检测更新
|
||||
MarketConfigure.init(this, "442eab382e6a49649e3402115bd8837f", MarketConfigure.MarketDeviceType.DEVICE_TYPE_PHONE);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import com.rs.macall.androidx.basemodel.utils.BitMapUtils;
|
|||
import com.rs.macall.androidx.basemodel.utils.LogUtils;
|
||||
import com.ycgis.macall.personalcenter.R;
|
||||
import com.ycgis.macall.personalcenter.m.adapterbean.BluetoothOV;
|
||||
import com.ycgis.macall.personalcenter.m.datamodel.PrintData;
|
||||
import com.ycgis.macall.personalcenter.m.datamodel.PrintModel;
|
||||
import com.ycgis.macall.personalcenter.m.provider.BluetoothBroadcastReceiver;
|
||||
import com.ycgis.macall.personalcenter.v.adapter.BluetoothListAdapter;
|
||||
|
|
@ -105,12 +106,12 @@ public class BluetoothManage {
|
|||
}
|
||||
|
||||
// 发送数据
|
||||
public boolean sendData(List<PrintModel> dataList) {
|
||||
public boolean sendData(List<PrintData> dataList) {
|
||||
if (outputStream != null) {
|
||||
if (dataList == null) return false;
|
||||
try {
|
||||
for (int i = 0; i < dataList.size(); i++) {
|
||||
PrintModel printModel = dataList.get(i);
|
||||
PrintData printModel = dataList.get(i);
|
||||
if (printModel.getPrintType() == 1) {
|
||||
outputStream.write(printModel.getContent().getBytes("GBK")); // 部分打印机需GBK编码
|
||||
} else if (printModel.getPrintType() == 2) {
|
||||
|
|
|
|||
|
|
@ -103,16 +103,16 @@ public class BluetoothActivity extends BaseViewBindActivity<ActivityBluetoothBin
|
|||
if (v.getId() == R.id.btn_printer) {
|
||||
//{"content":"二维码内容","printType":2},{"content":"base64","printType":3}
|
||||
String prContent = "[{\"content\":\"皖A97B21\n\",\"printType\":1},{\"content\":\"测试全部中文\",\"printType\":2}]";
|
||||
Type type = new TypeToken<List<PrintModel>>() {
|
||||
}.getType();
|
||||
List<PrintModel> data = new Gson().fromJson(prContent, type);
|
||||
boolean b = BluetoothSocket.getInstance().sendData(data);
|
||||
if (b) {
|
||||
ToastUtil.centered(getContext(),"打印完成");
|
||||
} else {
|
||||
ToastUtil.centered(getContext(),"打印失败");
|
||||
// mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-4", "打印失败!");
|
||||
}
|
||||
// Type type = new TypeToken<List<PrintModel>>() {
|
||||
// }.getType();
|
||||
// List<PrintModel> data = new Gson().fromJson(prContent, type);
|
||||
// boolean b = BluetoothSocket.getInstance().sendData(data);
|
||||
// if (b) {
|
||||
// ToastUtil.centered(getContext(),"打印完成");
|
||||
// } else {
|
||||
// ToastUtil.centered(getContext(),"打印失败");
|
||||
//// mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-4", "打印失败!");
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@ import android.annotation.SuppressLint;
|
|||
import android.app.Activity;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.location.Location;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
|
@ -19,7 +21,11 @@ import android.view.ViewGroup;
|
|||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.WebSettings;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.MainThread;
|
||||
|
||||
import com.gengcon.www.jcprintersdk.bean.PaperInfo;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.just.agentweb.AgentWeb;
|
||||
|
|
@ -29,6 +35,7 @@ import com.king.zxing.CameraScan;
|
|||
import com.rs.macall.androidx.basemodel.base.BaseViewBindActivity;
|
||||
import com.rs.macall.androidx.basemodel.callback.CustomClickListener;
|
||||
import com.rs.macall.androidx.basemodel.callback.PermissionListener;
|
||||
import com.rs.macall.androidx.basemodel.utils.BitMapUtils;
|
||||
import com.rs.macall.androidx.basemodel.utils.HandlerUtils;
|
||||
import com.rs.macall.androidx.basemodel.utils.LogUtils;
|
||||
import com.rs.macall.androidx.basemodel.utils.StatusBarUtil;
|
||||
|
|
@ -43,9 +50,11 @@ import com.ruansee.macall.unifyservemodulesdk.bean.ComponentBaseBean;
|
|||
import com.ruansee.macall.unifyservemodulesdk.bean.FaceIdentifyBean;
|
||||
import com.ruansee.macall.unifyservemodulesdk.bean.NFCBean;
|
||||
import com.ruansee.macall.unifyservemodulesdk.bean.OcrSfzBean;
|
||||
import com.ycgis.macall.jcBluetooth.PrintUtil;
|
||||
import com.ycgis.macall.personalcenter.BuildConfig;
|
||||
import com.ycgis.macall.personalcenter.R;
|
||||
import com.ycgis.macall.personalcenter.databinding.ActivityOpenAppBinding;
|
||||
import com.ycgis.macall.personalcenter.m.datamodel.PrintData;
|
||||
import com.ycgis.macall.personalcenter.m.datamodel.PrintModel;
|
||||
import com.ycgis.macall.personalcenter.m.model.SelectFileOptions;
|
||||
import com.ycgis.macall.personalcenter.p.app.CrashHandler;
|
||||
|
|
@ -66,6 +75,8 @@ import com.ycgis.zpSDK.BluetoothSocket;
|
|||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
|
|
@ -307,36 +318,6 @@ public class OpenAppActivity extends BaseViewBindActivity<ActivityOpenAppBinding
|
|||
// }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 绑定远程服务RemoteService
|
||||
*/
|
||||
// private void initService() {
|
||||
// Log.w(TAG, "initService");
|
||||
// Intent intent = new Intent(getContext(), RemoteService.class);
|
||||
//// intent.setComponent(new ComponentName("com.hongri.webview", "com.hongri.webview.service.RemoteService"));
|
||||
// bindService(intent, mConn, BIND_AUTO_CREATE);
|
||||
// }
|
||||
//
|
||||
// private final ServiceConnection mConn = new ServiceConnection() {
|
||||
// @Override
|
||||
// public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
//// Log.w(TAG, "onServiceConnected");
|
||||
// //当Service绑定成功时,通过Binder获取到远程服务代理
|
||||
// calculateInterface = CalculateInterface.Stub.asInterface(service);
|
||||
//
|
||||
// String url = getUrl();
|
||||
// LogUtils.d(TAG, url);
|
||||
//// mAgentWeb.getUrlLoader().loadUrl("file:///android_asset/TestJs.html");
|
||||
// mAgentWeb.getUrlLoader().loadUrl(url);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onServiceDisconnected(ComponentName name) {
|
||||
//// Log.d(TAG, "onServiceDisconnected");
|
||||
// calculateInterface = null;
|
||||
// }
|
||||
// };
|
||||
private void createFileDir(String fileDirName) {
|
||||
File file = new File(fileDirName);
|
||||
if (file.exists()) return;
|
||||
|
|
@ -868,11 +849,11 @@ public class OpenAppActivity extends BaseViewBindActivity<ActivityOpenAppBinding
|
|||
return;
|
||||
}
|
||||
BluetoothDevice remoteDevice = BluetoothSocket.getInstance().getRemoteDevice();
|
||||
if (remoteDevice!=null){
|
||||
ToastUtil.centered(getContext(),"蓝牙已连接");
|
||||
if (remoteDevice != null) {
|
||||
ToastUtil.centered(getContext(), "蓝牙已连接");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothResult", "1", "蓝牙已连接!");
|
||||
}else {
|
||||
openBluetoothFragment();
|
||||
} else {
|
||||
openBluetoothFragment(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -897,12 +878,92 @@ public class OpenAppActivity extends BaseViewBindActivity<ActivityOpenAppBinding
|
|||
* "pageHeight":100
|
||||
* }
|
||||
* ]
|
||||
*
|
||||
* @param json
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public void printContentsJSON(String json) {
|
||||
ToastUtil.centered(getContext(),"JS调起打印事件");
|
||||
LogUtils.w(TAG,"打印内容:"+json);
|
||||
ToastUtil.centered(getContext(), "JS调起打印事件");
|
||||
LogUtils.w(TAG, "打印内容:" + json);
|
||||
if (StringUtil.isNullOrEmpty(json)) {
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-3", "没有打印内容!");
|
||||
return;
|
||||
}
|
||||
Type type = new TypeToken<List<PrintData>>() {
|
||||
}.getType();
|
||||
List<PrintData> data = new Gson().fromJson(json, type);
|
||||
boolean b = BluetoothSocket.getInstance().sendData(data);
|
||||
if (b) {
|
||||
ToastUtil.centered(getContext(), "打印完成");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothResult", "2", "打印完成!");
|
||||
} else {
|
||||
ToastUtil.centered(getContext(), "打印失败");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-4", "打印失败!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JavascriptInterface
|
||||
public void openJCBluetooth() {
|
||||
BluetoothManage instance = BluetoothManage.getInstance();
|
||||
if (!instance.init()) {
|
||||
ToastUtil.centered(getContext(), "当前设备不支持蓝牙!");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-1", "当前设备不支持蓝牙");
|
||||
return;
|
||||
}
|
||||
if (!instance.isBluetoothOpen(getActivity(), true)) {
|
||||
ToastUtil.centered(getContext(), "请先打开蓝牙!");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-2", "蓝牙未打开");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PrintUtil.isConnection() == 0) {
|
||||
ToastUtil.centered(getContext(), "蓝牙已连接");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothResult", "1", "蓝牙已连接!");
|
||||
return;
|
||||
}
|
||||
openBluetoothFragment(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* [
|
||||
* {
|
||||
* "pageWidth": 100,
|
||||
* "pageHeight": 100,
|
||||
* "printData": [
|
||||
* {
|
||||
* "content": "文字内容",
|
||||
* "printType": 1,
|
||||
* "contentWidth": 100,
|
||||
* "contentHeight:": 90
|
||||
* },
|
||||
* {
|
||||
* "content": "二维码内容",
|
||||
* "printType": 2,
|
||||
* "zoomLevel": 5,
|
||||
* "contentWidth": 100,
|
||||
* "contentHeight:": 100
|
||||
* },
|
||||
* {
|
||||
* "content": "data:image/png;base64",
|
||||
* "printType": 3,
|
||||
* "contentWidth:": 90,
|
||||
* "contentHeight:": 90
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* ]
|
||||
* @param json
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public void printJCContentsJSON(String json) {
|
||||
if (PrintUtil.isConnection() != 0) {
|
||||
ToastUtil.centered(getContext(), "打印机未连接,请先链接打印机!");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-3", "打印机未连接");
|
||||
return;
|
||||
}
|
||||
ToastUtil.centered(getContext(), "JS调起打印事件");
|
||||
LogUtils.w(TAG, "打印内容:" + json);
|
||||
if (StringUtil.isNullOrEmpty(json)) {
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-3", "没有打印内容!");
|
||||
return;
|
||||
|
|
@ -910,29 +971,97 @@ public class OpenAppActivity extends BaseViewBindActivity<ActivityOpenAppBinding
|
|||
Type type = new TypeToken<List<PrintModel>>() {
|
||||
}.getType();
|
||||
List<PrintModel> data = new Gson().fromJson(json, type);
|
||||
boolean b = BluetoothSocket.getInstance().sendData(data);
|
||||
if (b) {
|
||||
ToastUtil.centered(getContext(),"打印完成");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothResult", "2", "打印完成!");
|
||||
} else {
|
||||
ToastUtil.centered(getContext(),"打印失败");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-4", "打印失败!");
|
||||
if (data == null){
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-3", "没有打印内容!");
|
||||
return;
|
||||
}
|
||||
List<String> jsonList = new ArrayList<>();
|
||||
List<String> infoList = new ArrayList<>();
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
PrintModel printModel = data.get(i);
|
||||
if (printModel == null)continue;
|
||||
//绘制内容
|
||||
boolean b = PrintUtil.drawLabelJson(printModel);
|
||||
if (!b)continue;
|
||||
//⽣成打印数据
|
||||
byte[] jsonByte = PrintUtil.getInstance().generateLabelJson();
|
||||
|
||||
try {
|
||||
jsonList.add(new String(jsonByte,"UTF-8"));
|
||||
String info = "{\"printerImageProcessingInfo\": {"+
|
||||
"\"orientation\": 0,"+
|
||||
"\"margin\": [3,3,3,3],"+
|
||||
"\"printQuantity\": 1,"+
|
||||
"\"horizontalOffset\": 0,"+
|
||||
"\"verticalOffset\": 0,"+//垂直偏移
|
||||
"\"width\":"+printModel.getPageWidth()+","+//画布宽度,单位mm
|
||||
"\"height\": "+printModel.getPageHeight()+","+//画布⾼度,单位mm
|
||||
"\"printMultiple\": 11.81,"+//打印倍率 200dpi的打印机为8,300dpi的打印机为11.81
|
||||
"\"epc\": \"\"}}";//RFID标签写⼊数据,B32R机器打印RFID标签时填充数据,其他场景默认”“
|
||||
infoList.add(info);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonList.isEmpty()){
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-3", "没有打印内容!");
|
||||
return;
|
||||
}
|
||||
|
||||
PrintUtil.startLabelPrintJob(1, 5, 1, 2, new Handler(Looper.getMainLooper()),jsonList ,infoList , new PrintUtil.PrintStatusCallback() {
|
||||
@Override
|
||||
public void onProgress(int pageIndex, int quantityIndex) {
|
||||
String progress = "打印进度:已打印到第" + pageIndex + "页,第" + quantityIndex + "份";
|
||||
LogUtils.w(progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, int printState) {
|
||||
String errorMessage = PrintUtil.ERROR_MESSAGES.containsKey(errorCode) ? PrintUtil.ERROR_MESSAGES.get(errorCode) : "未知错误";
|
||||
ToastUtil.centered(getContext(),errorMessage);
|
||||
LogUtils.e("onError",errorCode,printState);
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-4", "打印失败!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelJob(boolean isSuccess) {
|
||||
String s = isSuccess ? "打印已取消" : "取消失败";
|
||||
LogUtils.i("onCancelJob",s);
|
||||
ToastUtil.centered(getContext(),s);
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-4", "打印失败!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrintComplete() {
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothResult", "2", "打印完成!");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void openBluetoothFragment() {
|
||||
|
||||
/**
|
||||
* 是否使用金辰
|
||||
* @param isJC
|
||||
*/
|
||||
private void openBluetoothFragment(boolean isJC) {
|
||||
// 在Activity中
|
||||
BluetoothDialogFragment dialog = new BluetoothDialogFragment();
|
||||
dialog.setBluetoothFragmentListener(new BluetoothFragmentListener() {
|
||||
@Override
|
||||
public void onClickBluetoothDevice(BluetoothDevice device) {
|
||||
if (isJC){
|
||||
linkBluetoothJC(device);
|
||||
}else {
|
||||
linkBluetooth(device);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", code+"",msg);
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", code + "", msg);
|
||||
}
|
||||
});
|
||||
dialog.show(getSupportFragmentManager(), "MyDialog");
|
||||
|
|
@ -946,13 +1075,33 @@ public class OpenAppActivity extends BaseViewBindActivity<ActivityOpenAppBinding
|
|||
private void linkBluetooth(BluetoothDevice device) {
|
||||
baseShowDialog("正在链接");
|
||||
if (!BluetoothSocket.getInstance().ConnectPrinter(device.getAddress())) {
|
||||
ToastUtil.centered(getContext(),"蓝牙连接失败");
|
||||
ToastUtil.centered(getContext(), "蓝牙连接失败");
|
||||
//Toast.makeText(this, "Connect Fail", Toast.LENGTH_SHORT).show();
|
||||
baseDismissDialog();
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-3", "蓝牙连接失败!");
|
||||
isLinkPrinter = false;
|
||||
} else {
|
||||
ToastUtil.centered(getContext(),"蓝牙已连接");
|
||||
ToastUtil.centered(getContext(), "蓝牙已连接");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothResult", "1", "蓝牙已连接!");
|
||||
baseDismissDialog();
|
||||
isLinkPrinter = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*链接蓝牙
|
||||
*/
|
||||
private void linkBluetoothJC(BluetoothDevice device) {
|
||||
baseShowDialog("正在链接");
|
||||
int i = PrintUtil.connectBluetoothPrinter(device.getAddress());
|
||||
if (i == -1) {
|
||||
ToastUtil.centered(getContext(), "蓝牙连接失败");
|
||||
//Toast.makeText(this, "Connect Fail", Toast.LENGTH_SHORT).show();
|
||||
baseDismissDialog();
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothError", "-3", "蓝牙连接失败!");
|
||||
isLinkPrinter = false;
|
||||
} else {
|
||||
ToastUtil.centered(getContext(), "蓝牙已连接");
|
||||
mAgentWeb.getJsAccessEntrace().quickCallJs("callBluetoothResult", "1", "蓝牙已连接!");
|
||||
baseDismissDialog();
|
||||
isLinkPrinter = true;
|
||||
|
|
|
|||
|
|
@ -84,21 +84,22 @@ public class BluetoothDialogFragment extends DialogFragment {
|
|||
boolean init = BluetoothManage.getInstance().init();
|
||||
if (!init) {
|
||||
ToastUtil.centered(getContext(), "当前设备不支持蓝牙!");
|
||||
if (bluetoothFragmentListener!=null) bluetoothFragmentListener.onError(-1,"当前设备不支持蓝牙");
|
||||
if (bluetoothFragmentListener != null)
|
||||
bluetoothFragmentListener.onError(-1, "当前设备不支持蓝牙");
|
||||
dismiss();
|
||||
return;
|
||||
}
|
||||
if (!BluetoothManage.getInstance().isBluetoothOpen(getActivity(), true)) {
|
||||
ToastUtil.centered(getContext(), "请先打开蓝牙!");
|
||||
if (bluetoothFragmentListener!=null) bluetoothFragmentListener.onError(-2,"蓝牙未打卡");
|
||||
if (bluetoothFragmentListener != null) bluetoothFragmentListener.onError(-2, "蓝牙未打卡");
|
||||
dismiss();
|
||||
return;
|
||||
}
|
||||
btAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
BluetoothDevice remoteDevice = BluetoothSocket.getInstance().getRemoteDevice();
|
||||
if (remoteDevice != null){
|
||||
viewBinding.tvPrinters.setText("已连接|"+remoteDevice.getName());
|
||||
}else {
|
||||
if (remoteDevice != null) {
|
||||
viewBinding.tvPrinters.setText("已连接|" + remoteDevice.getName());
|
||||
} else {
|
||||
viewBinding.tvPrinters.setText("未连接打印机");
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +114,7 @@ public class BluetoothDialogFragment extends DialogFragment {
|
|||
getActivity().registerReceiver(mBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
private void onBindView(int viewId){
|
||||
private void onBindView(int viewId) {
|
||||
if (viewId == R.id.btn_search) {
|
||||
discovry_do();
|
||||
}
|
||||
|
|
@ -132,7 +133,7 @@ public class BluetoothDialogFragment extends DialogFragment {
|
|||
// 设置Dialog宽度
|
||||
if (getDialog() != null && getDialog().getWindow() != null) {
|
||||
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
DimensionConvert.dip2px(getContext(),680));
|
||||
DimensionConvert.dip2px(getContext(), 640));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,8 +157,8 @@ public class BluetoothDialogFragment extends DialogFragment {
|
|||
Set<BluetoothDevice> PairedDevices = btAdapter.getBondedDevices();
|
||||
if (PairedDevices.size() > 0) {
|
||||
for (BluetoothDevice device : PairedDevices) {
|
||||
if (device == null)continue;
|
||||
if (StringUtil.isNullOrEmpty(device.getAddress()))continue;
|
||||
if (device == null) continue;
|
||||
if (StringUtil.isNullOrEmpty(device.getAddress())) continue;
|
||||
// String device_info = device.getName()+"\n"+device.getAddress();
|
||||
pdDataList.add(device);
|
||||
}
|
||||
|
|
@ -172,7 +173,7 @@ public class BluetoothDialogFragment extends DialogFragment {
|
|||
listAdapter1.setListClickListener(new SimpleListClickListener() {
|
||||
@Override
|
||||
public void onSingleClick(View v, int pointer) {
|
||||
if (bluetoothFragmentListener != null){
|
||||
if (bluetoothFragmentListener != null) {
|
||||
bluetoothFragmentListener.onClickBluetoothDevice(listAdapter1.getDataItem(pointer));
|
||||
}
|
||||
dismiss();
|
||||
|
|
@ -208,9 +209,8 @@ public class BluetoothDialogFragment extends DialogFragment {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private void initSearch(BluetoothDevice device) {
|
||||
if (StringUtil.isNullOrEmpty(device.getAddress()))return;
|
||||
if (StringUtil.isNullOrEmpty(device.getAddress())) return;
|
||||
if (listAdapter2 == null) {
|
||||
searchDataList.add(device);
|
||||
listAdapter2 = new BluetoothListAdapter(getContext(), searchDataList);
|
||||
|
|
@ -218,7 +218,7 @@ public class BluetoothDialogFragment extends DialogFragment {
|
|||
listAdapter2.setListClickListener(new SimpleListClickListener() {
|
||||
@Override
|
||||
public void onSingleClick(View v, int pointer) {
|
||||
if (bluetoothFragmentListener != null){
|
||||
if (bluetoothFragmentListener != null) {
|
||||
bluetoothFragmentListener.onClickBluetoothDevice(listAdapter2.getDataItem(pointer));
|
||||
}
|
||||
dismiss();
|
||||
|
|
@ -237,8 +237,11 @@ public class BluetoothDialogFragment extends DialogFragment {
|
|||
Log.d("BT", "----------onReceive----------" + action);
|
||||
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
|
||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
|
||||
initSearch(device);
|
||||
boolean supportBluetoothType = device.getType() == BluetoothDevice.DEVICE_TYPE_CLASSIC || device.getType() == BluetoothDevice.DEVICE_TYPE_DUAL;
|
||||
if (supportBluetoothType) {
|
||||
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
|
||||
initSearch(device);
|
||||
}
|
||||
}
|
||||
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
|
||||
viewBinding.btnSearch.setVisibility(View.VISIBLE);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.google.zxing.common.BitMatrix;
|
|||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.rs.macall.androidx.basemodel.utils.BitMapUtils;
|
||||
import com.rs.macall.androidx.basemodel.utils.StringUtil;
|
||||
import com.ycgis.macall.personalcenter.m.datamodel.PrintData;
|
||||
import com.ycgis.macall.personalcenter.m.datamodel.PrintModel;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
|
@ -193,16 +194,15 @@ public class BluetoothSocket {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
// 发送数据
|
||||
public boolean sendData(List<PrintModel> dataList) {
|
||||
public boolean sendData(List<PrintData> dataList) {
|
||||
if (!isConnected())return false;
|
||||
if (myOutStream != null) {
|
||||
if (dataList == null) return false;
|
||||
try {
|
||||
boolean isNewline = dataList.size()>1;
|
||||
for (int i = 0; i < dataList.size(); i++) {
|
||||
PrintModel printModel = dataList.get(i);
|
||||
PrintData printModel = dataList.get(i);
|
||||
if (printModel == null) continue;
|
||||
if (printModel.getPrintType() == 1) {
|
||||
String content = printModel.getContent();
|
||||
|
|
@ -235,8 +235,8 @@ public class BluetoothSocket {
|
|||
}
|
||||
|
||||
|
||||
public boolean printText(String content, PrintModel model) throws UnsupportedEncodingException {
|
||||
zpPrinter zpSDK = new zpPrinter();
|
||||
public boolean printText(String content, PrintData model) throws UnsupportedEncodingException {
|
||||
ZpPrinter zpSDK = new ZpPrinter();
|
||||
zpSDK.pageSetup(model.getPageWidth(), model.getPageHeight());
|
||||
//zpSDK.drawBarCode(10,10,"123456789012",1,0,4,80);
|
||||
zpSDK.alignLeft();
|
||||
|
|
@ -245,10 +245,10 @@ public class BluetoothSocket {
|
|||
return Write(print.getBytes(GBK));
|
||||
}
|
||||
|
||||
public boolean printBitMap(PrintModel model){
|
||||
public boolean printBitMap(PrintData model){
|
||||
Bitmap bitmap = BitMapUtils.base64ToBitmap(model.getContent());
|
||||
if (bitmap == null) return false;
|
||||
zpPrinter zpSDK = new zpPrinter();
|
||||
ZpPrinter zpSDK = new ZpPrinter();
|
||||
zpSDK.pageSetup(model.getPageWidth(), model.getPageHeight());
|
||||
zpSDK.drawGraphic(10,10,model.getContentHeight(),model.getContentWidth(),bitmap);
|
||||
byte[] bytes = zpSDK.printByte(0, 1);
|
||||
|
|
@ -256,8 +256,8 @@ public class BluetoothSocket {
|
|||
return Write(gzipBytes); // 部分打印机需GBK编码
|
||||
}
|
||||
|
||||
public boolean printQrCode(PrintModel model) {
|
||||
zpPrinter zpSDK = new zpPrinter();
|
||||
public boolean printQrCode(PrintData model) {
|
||||
ZpPrinter zpSDK = new ZpPrinter();
|
||||
try {
|
||||
zpSDK.pageSetup(model.getPageWidth(), model.getPageHeight());
|
||||
zpSDK.drawQrCode(10, 10, model.getContent(), 0, model.getZoomLevel(), 4);
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class printPDF {
|
||||
public class PrintPDF {
|
||||
|
||||
Context mCotext;
|
||||
ArrayList<Bitmap> mbitmaps=null;
|
||||
|
||||
public printPDF(Context con)
|
||||
public PrintPDF(Context con)
|
||||
{
|
||||
mCotext = con;
|
||||
mbitmaps = new ArrayList<Bitmap>();
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
package com.ycgis.zpSDK;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.usb.UsbConstants;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbEndpoint;
|
||||
import android.hardware.usb.UsbInterface;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class UsbSocket {
|
||||
|
||||
Context context;
|
||||
String TAG="zpSDK";
|
||||
static UsbSocket mUsbSocket=null;
|
||||
private int sysVersion;
|
||||
public static UsbSocket getInstance(Context context)
|
||||
{
|
||||
if (mUsbSocket==null)
|
||||
mUsbSocket=new UsbSocket(context);
|
||||
return mUsbSocket;
|
||||
}
|
||||
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
|
||||
UsbManager mUsbManager;
|
||||
|
||||
UsbSocket(Context context)
|
||||
{
|
||||
this.context=context;
|
||||
sysVersion = Integer.parseInt(Build.VERSION.SDK);
|
||||
// if(sysVersion<19)
|
||||
// context.onNewIntent(context.getIntent());
|
||||
context.registerReceiver(mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED));
|
||||
context.registerReceiver(mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver()
|
||||
{
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
String action = intent.getAction();
|
||||
if(UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action))
|
||||
{
|
||||
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
||||
if(device.getVendorId()==1155&&device.getProductId()==22339)
|
||||
{
|
||||
Log.e(TAG, "USB打印机已接入");
|
||||
Toast.makeText(context,"USB打印机已接入", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
if(UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action))
|
||||
{
|
||||
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
||||
if(device.getVendorId()==1155&&device.getProductId()==22339)
|
||||
{
|
||||
Log.e(TAG, "USB打印机已断开");
|
||||
Toast.makeText(context,"USB打印机已断开", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void ConnectPrinter()
|
||||
{
|
||||
context.registerReceiver(mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED));
|
||||
context.registerReceiver(mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));
|
||||
}
|
||||
|
||||
public String Write(byte[] prnData)
|
||||
{
|
||||
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
|
||||
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
|
||||
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
|
||||
while(deviceIterator.hasNext())
|
||||
{
|
||||
//Log.d("zpSDK","USB deviceIterator");
|
||||
UsbDevice usbDevice = deviceIterator.next();
|
||||
//Log.d("zpSDK",String.valueOf(usbDevice.getVendorId())+","+String.valueOf(usbDevice.getProductId()));
|
||||
if(usbDevice.getVendorId()!=1155||usbDevice.getProductId()!=22339)continue;
|
||||
if(writePort(usbManager,usbDevice,prnData))
|
||||
{
|
||||
Log.e(TAG, "USB打印成功");
|
||||
|
||||
//Looper.prepare();
|
||||
Toast.makeText(context,"USB打印成功", Toast.LENGTH_LONG).show();
|
||||
//Looper.loop();
|
||||
return "USB打印成功";
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e(TAG, "USB打印失败");
|
||||
// Looper.prepare();
|
||||
Toast.makeText(context,"USB打印失败", Toast.LENGTH_LONG).show();
|
||||
// Looper.loop();
|
||||
return "USB打印失败";
|
||||
}
|
||||
}
|
||||
Log.e(TAG, "无法连接USB打印机");
|
||||
// Looper.prepare();
|
||||
Toast.makeText(context,"无法连接USB打印机", Toast.LENGTH_LONG).show();
|
||||
// Looper.loop();
|
||||
return "无法连接USB打印机";
|
||||
}
|
||||
|
||||
boolean writePort(UsbManager manager,UsbDevice usbDev, byte[] data)
|
||||
{
|
||||
boolean success=false;
|
||||
UsbEndpoint end_in = null;
|
||||
UsbEndpoint end_out = null;
|
||||
byte[] buffer = new byte[64];
|
||||
try {
|
||||
UsbInterface interf = usbDev.getInterface(0);
|
||||
UsbDeviceConnection connection = manager.openDevice(usbDev);//连接usb设备
|
||||
if (connection == null) {
|
||||
Log.d(TAG, "mUsbDeviceConnection can't be null");
|
||||
return false;
|
||||
}
|
||||
if (connection.claimInterface(interf, true)) {
|
||||
//Log.d(TAG,"claimInterface success");
|
||||
int endpointCount = interf.getEndpointCount();
|
||||
for (int i = 0; i < endpointCount; i++) {
|
||||
UsbEndpoint endpoint = interf.getEndpoint(i);
|
||||
if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
|
||||
if (UsbConstants.USB_DIR_IN == endpoint.getDirection()) {
|
||||
end_in = endpoint;//获取读数据通道
|
||||
} else if(UsbConstants.USB_DIR_OUT == endpoint.getDirection()){
|
||||
end_out = endpoint;//获取写数据通道
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
connection.close();
|
||||
Log.d(TAG,"claimInterface fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (end_out != null)
|
||||
{
|
||||
// bulkTransfer通过给定的endpoint来进行大量的数据传输,传输的方向取决于该节点的方向,
|
||||
// 传输成果返回传输字节数组的长度,失败返回负数
|
||||
int send_ret = connection.bulkTransfer(end_out, buffer,buffer.length,0 );
|
||||
send_ret=0;
|
||||
int total_length=data.length;
|
||||
//API28之前的系统,bulkTransfer最大包不能超过16384,所以要拆包
|
||||
int pack = data.length / 16384;
|
||||
int j = 0;
|
||||
for (j = 0; j < pack; j++) {
|
||||
byte[] newBuffer = Arrays.copyOfRange(data, j * 16384, 16384 + j * 16384);
|
||||
// 参数依次为:下行端点,字节数组消息,消息长度,响应时间
|
||||
send_ret += connection.bulkTransfer(end_out, newBuffer, newBuffer.length, 0);
|
||||
}
|
||||
if(send_ret<total_length){
|
||||
byte[] newBuffer = Arrays.copyOfRange(data, j * 16384, total_length);
|
||||
send_ret += connection.bulkTransfer(end_out, newBuffer, newBuffer.length, 0);
|
||||
}
|
||||
Log.d(TAG,"send Data:"+","+String.valueOf(send_ret));
|
||||
if (send_ret >= data.length)success=true;
|
||||
if (connection != null)
|
||||
{
|
||||
connection.releaseInterface(interf);
|
||||
connection.close();
|
||||
}
|
||||
interf = null;
|
||||
connection = null;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
public byte[] Read(int Timeout)
|
||||
{
|
||||
// UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
|
||||
// UsbDeviceConnection connection = manager.openDevice(usbDev);
|
||||
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
|
||||
HashMap<String,UsbDevice> deviceHashMap = usbManager.getDeviceList();
|
||||
Iterator<UsbDevice> iterator = deviceHashMap.values().iterator();
|
||||
|
||||
System.out.println("deviceHashMap.isEmpty()"+deviceHashMap.isEmpty());
|
||||
|
||||
UsbEndpoint inEndpoint=null;
|
||||
byte[] byte2 = new byte[1024];
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
UsbDevice usbDevice = iterator.next();
|
||||
if(usbDevice.getVendorId()!=1155||usbDevice.getProductId()!=22339)continue;
|
||||
UsbInterface usbInterface = usbDevice.getInterface(0);//USBEndpoint为读写数据所需的节点
|
||||
UsbDeviceConnection connection = usbManager.openDevice(usbDevice);
|
||||
|
||||
if (connection.claimInterface(usbInterface, true)) {
|
||||
int endpointCount = usbInterface.getEndpointCount();
|
||||
for (int i = 0; i < endpointCount; i++) {
|
||||
UsbEndpoint endpoint = usbInterface.getEndpoint(i);
|
||||
if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
|
||||
if (UsbConstants.USB_DIR_IN == endpoint.getDirection()) {
|
||||
inEndpoint = endpoint;//获取读数据通道
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
connection.close();
|
||||
Log.d(TAG,"claimInterface fail");
|
||||
return null;
|
||||
}
|
||||
|
||||
int ret = connection.bulkTransfer(inEndpoint, byte2, byte2.length, Timeout);
|
||||
Log.i(TAG, "ret:" + ret);
|
||||
Log.i(TAG, "bat is ok length:" + byte2.length);
|
||||
for (Byte byte1 : byte2) {
|
||||
Log.i(TAG,"byte1 :" + byte1);
|
||||
}
|
||||
}
|
||||
return byte2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
package com.ycgis.zpSDK;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class WifiSocket {
|
||||
|
||||
public static String ErrorMessage = "No Error";
|
||||
private static Socket wifiSocket = null;
|
||||
private static OutputStream myOutStream = null;
|
||||
private static InputStream myInStream = null;
|
||||
private static WifiSocket mWifiSocket = null;
|
||||
wifiListener mwifiListener=null;
|
||||
boolean isWrite = true;
|
||||
boolean isRead = true;
|
||||
|
||||
private WifiSocket(wifiListener listener) {
|
||||
mwifiListener = listener;
|
||||
}
|
||||
|
||||
public static WifiSocket getInstance(wifiListener listener){
|
||||
if (mWifiSocket==null)
|
||||
mWifiSocket = new WifiSocket(listener);
|
||||
return mWifiSocket;
|
||||
}
|
||||
|
||||
|
||||
public void ConnectPrinter(String ip) {
|
||||
InetAddress mInetaddr = null;
|
||||
int port = 9100;
|
||||
if (ip == null||ip.equals("")) {
|
||||
} else {
|
||||
try {
|
||||
mInetaddr = InetAddress.getByName(ip);
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
InetAddress finalMInetaddr = mInetaddr;
|
||||
Timer timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wifiSocket = new Socket(finalMInetaddr, port);
|
||||
|
||||
myOutStream = wifiSocket.getOutputStream();
|
||||
myInStream = wifiSocket.getInputStream();
|
||||
mwifiListener.receivedmsg("finish");
|
||||
} catch (UnknownHostException var4) {
|
||||
mwifiListener.receivedmsg("timeout");
|
||||
} catch (IOException var5) {
|
||||
mwifiListener.receivedmsg("timeout");
|
||||
}
|
||||
}
|
||||
}, 1500);
|
||||
|
||||
mwifiListener.receivedmsg("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean disconncet() {
|
||||
try {
|
||||
Thread.sleep(1000L);
|
||||
} catch (InterruptedException var6) {
|
||||
}
|
||||
mwifiListener.receivedmsg("");
|
||||
mwifiListener.receivedstatus(null);
|
||||
if (myOutStream != null) {
|
||||
try {
|
||||
myOutStream.flush();
|
||||
} catch (IOException var5) {
|
||||
}
|
||||
|
||||
try {
|
||||
myOutStream.close();
|
||||
} catch (IOException var4) {
|
||||
}
|
||||
|
||||
myOutStream = null;
|
||||
}
|
||||
|
||||
if (myInStream != null) {
|
||||
try {
|
||||
myInStream.close();
|
||||
} catch (IOException var3) {
|
||||
}
|
||||
|
||||
myInStream = null;
|
||||
}
|
||||
|
||||
if (wifiSocket != null) {
|
||||
try {
|
||||
wifiSocket.close();
|
||||
} catch (IOException var2) {
|
||||
}
|
||||
|
||||
wifiSocket = null;
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(200L);
|
||||
} catch (InterruptedException var1) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Write(byte[] Data) {
|
||||
|
||||
isWrite = true;
|
||||
if (isWrite)
|
||||
{
|
||||
isWrite = false;
|
||||
new Thread(){
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try {
|
||||
myOutStream.write(Data);
|
||||
isWrite = true;
|
||||
} catch (IOException var2) {
|
||||
mwifiListener.receivedmsg("发送数据失败");
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Write(byte[] Data, int DataLen) {
|
||||
|
||||
isWrite = true;
|
||||
if (isWrite)
|
||||
{
|
||||
isWrite = false;
|
||||
new Thread(){
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try {
|
||||
myOutStream.write(Data, 0, DataLen);
|
||||
isWrite = true;
|
||||
} catch (IOException var2) {
|
||||
mwifiListener.receivedmsg("发送数据失败");
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Flush() {
|
||||
int DataLen = 0;
|
||||
|
||||
try {
|
||||
DataLen = myInStream.available();
|
||||
} catch (IOException var4) {
|
||||
}
|
||||
|
||||
for(int i = 0; i < DataLen; ++i) {
|
||||
try {
|
||||
myInStream.read();
|
||||
} catch (IOException var3) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Read(int Timeout) {
|
||||
new Thread(){
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytes;
|
||||
int len = 0;
|
||||
|
||||
try {
|
||||
len = myInStream.available();
|
||||
} catch (IOException var4) {
|
||||
}
|
||||
|
||||
if (len>0)
|
||||
{
|
||||
try {
|
||||
myInStream.skip(myInStream.available());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
try {
|
||||
bytes = myInStream.read(buffer);
|
||||
if (bytes>0)
|
||||
{
|
||||
final byte[] data = new byte[bytes];
|
||||
System.arraycopy(buffer, 0, data, 0, bytes);
|
||||
mwifiListener.receivedstatus(data);
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import java.io.FileNotFoundException;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
public class zpPrinter
|
||||
public class ZpPrinter
|
||||
{
|
||||
private Context context;
|
||||
static int w;
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
package com.ycgis.zpSDK;
|
||||
|
||||
public interface wifiListener {
|
||||
|
||||
void receivedmsg(String msg);
|
||||
void receivedstatus(byte[] statue);
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:background="@drawable/round_top_white_8"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="680dp">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
## This file is automatically generated by Android Studio.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file should *NOT* be checked into Version Control Systems,
|
||||
## This file must *NOT* be checked into Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
#
|
||||
# Location of the SDK. This is only used by Gradle.
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
#Wed Jun 25 16:46:01 CST 2025
|
||||
sdk.dir=D\:\\Program Files\\sdk
|
||||
|
|
@ -4,7 +4,6 @@ plugins {
|
|||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.ruansee.macall.testwebview"
|
||||
|
|
@ -58,8 +57,6 @@ dependencies {
|
|||
|
||||
//加载动画
|
||||
implementation 'com.wang.avi:library:2.1.3'
|
||||
//视频播放器 饺子视频播放器
|
||||
implementation 'cn.jzvd:jiaozivideoplayer:7.7.0'
|
||||
|
||||
// Glide 设置 OkHttp 请求的注解 依赖
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
|
|
@ -70,4 +67,23 @@ dependencies {
|
|||
implementation files('libs/com.code.base.jar')
|
||||
implementation files('libs/unifyservemoduleSDK_V1.2.231127.aar')
|
||||
implementation project(':BaseModel')
|
||||
|
||||
//Ormlite 数据库
|
||||
implementation 'com.j256.ormlite:ormlite-android:5.1'
|
||||
implementation 'com.j256.ormlite:ormlite-core:5.1'
|
||||
|
||||
implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
|
||||
implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
|
||||
implementation 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
|
||||
//模拟器
|
||||
implementation 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
|
||||
implementation 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
|
||||
|
||||
//视频播放器 饺子视频播放器
|
||||
implementation files('libs/jiaozivideoplayer-debug.aar')
|
||||
|
||||
//视频播放器 饺子视频播放器
|
||||
implementation files('libs/JCamera-release.aar')
|
||||
|
||||
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -13,7 +13,8 @@
|
|||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS"/>
|
||||
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
|
||||
<application
|
||||
android:name=".app.RuanseeApp"
|
||||
|
|
@ -24,18 +25,30 @@
|
|||
android:roundIcon="@drawable/icon_login2"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.NewPersonalCenter">
|
||||
<activity android:name=".activity.SettingActivity"/>
|
||||
<activity android:name=".activity.StartActivity">
|
||||
<activity android:name=".activity.RecordVideoActivity"></activity>
|
||||
<activity android:name=".activity.PlayVideoActivity" />
|
||||
<activity
|
||||
android:name=".activity.WorkbenchActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".activity.SettingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".activity.StartActivity"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".activity.MainActivity"/>
|
||||
<activity android:name=".activity.OpenAppActivity"
|
||||
<activity
|
||||
android:name=".activity.MainActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".activity.OpenAppActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@ import android.os.Bundle;
|
|||
import android.view.View;
|
||||
|
||||
import com.rs.macall.androidx.basemodel.base.BaseViewBindActivity;
|
||||
import com.rs.macall.androidx.basemodel.callback.CustomClickListener;
|
||||
import com.rs.macall.androidx.basemodel.utils.StringUtil;
|
||||
import com.rs.macall.androidx.basemodel.utils.ToastUtil;
|
||||
import com.ruansee.macall.testwebview.app.AppCacheData;
|
||||
import com.ruansee.macall.testwebview.app.ContinuouslyClickListener;
|
||||
import com.ruansee.macall.testwebview.app.RuanseeApp;
|
||||
import com.ruansee.macall.testwebview.databinding.ActivityMainBinding;
|
||||
|
||||
|
|
@ -52,13 +54,17 @@ public class MainActivity extends BaseViewBindActivity<ActivityMainBinding> {
|
|||
}
|
||||
viewBinding.mainUserName.setText(String.format("%s(%s)",appCacheData.getUserName(),appCacheData.getDeptCode()));
|
||||
viewBinding.mainDeptName.setText(StringUtil.get(appCacheData.getDeptName(),appCacheData.getDeptCode()));
|
||||
viewBinding.imageView3.setOnClickListener(new ContinuouslyClickListener(){
|
||||
@Override
|
||||
public void onFastClick(View v) {
|
||||
startActivity(new Intent(getContext(),WorkbenchActivity.class));
|
||||
}
|
||||
});
|
||||
String idCardNum = appCacheData.getIdCardNum();
|
||||
if (StringUtil.isNullOrEmpty(idCardNum)){
|
||||
viewBinding.mainUserSfzh.setText("暂无");
|
||||
}else {
|
||||
char[] chars = idCardNum.toCharArray();
|
||||
//3424221993 0 6 0 4 1 4 1 3
|
||||
//0123456789 10 11 12 13 14 15
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i <chars.length; i++) {
|
||||
if (i>= 8 && i<=14){
|
||||
|
|
@ -79,7 +85,7 @@ public class MainActivity extends BaseViewBindActivity<ActivityMainBinding> {
|
|||
intent.putExtra(OpenAppActivity.paramKey2, appCacheData.getClientSecret());
|
||||
intent.putExtra(OpenAppActivity.paramKey3, appCacheData.getAppUrl());
|
||||
intent.putExtra(OpenAppActivity.paramKey9, appCacheData.getAppName());
|
||||
intent.putExtra(OpenAppActivity.paramKey10, "管理员");
|
||||
intent.putExtra(OpenAppActivity.paramKey10, "运维人员");
|
||||
intent.putExtra(OpenAppActivity.paramKey11, "18888686866");
|
||||
startActivity(intent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package com.ruansee.macall.testwebview.activity;
|
||||
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.rs.macall.androidx.basemodel.base.BaseViewBindActivity;
|
||||
import com.ruansee.macall.testwebview.databinding.ActivityPlayVideoBinding;
|
||||
import com.ruansee.macall.testwebview.model.JZMediaIjk;
|
||||
|
||||
import cn.jzvd.Jzvd;
|
||||
import cn.jzvd.JzvdStd;
|
||||
|
||||
public class PlayVideoActivity extends BaseViewBindActivity<ActivityPlayVideoBinding> {
|
||||
private String filePath;
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
protected ActivityPlayVideoBinding getViewBinding() {
|
||||
return ActivityPlayVideoBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readInstanceState(Bundle savedInstanceState) {
|
||||
filePath = getIntent().getStringExtra("filePath");
|
||||
name = getIntent().getStringExtra("name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start() {
|
||||
// 启用自动全屏时的方向旋转
|
||||
Jzvd.FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
|
||||
Jzvd.NORMAL_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
||||
|
||||
viewBinding.jzVideo.setUp(filePath, name, JzvdStd.SCREEN_NORMAL, JZMediaIjk.class);
|
||||
viewBinding.jzVideo.startVideo();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (Jzvd.backPress()) {
|
||||
return;
|
||||
}
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
Jzvd.releaseAllVideos();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package com.ruansee.macall.testwebview.activity;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import com.rs.macall.androidx.basemodel.base.BaseViewBindActivity;
|
||||
import com.rs.macall.androidx.basemodel.utils.BitMapUtils;
|
||||
import com.rs.macall.androidx.basemodel.utils.LogUtils;
|
||||
import com.rs.macall.androidx.basemodel.utils.ToastUtil;
|
||||
import com.ruansee.macall.testwebview.R;
|
||||
import com.ruansee.macall.testwebview.databinding.ActivityRecordVideoBinding;
|
||||
import com.ruansee.macall.testwebview.utils.FileUtils;
|
||||
import com.ycgis.macall.jcamera.CameraInterface;
|
||||
import com.ycgis.macall.jcamera.JCameraView;
|
||||
import com.ycgis.macall.jcamera.listener.ErrorListener;
|
||||
import com.ycgis.macall.jcamera.listener.JCameraListener;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class RecordVideoActivity extends BaseViewBindActivity<ActivityRecordVideoBinding> {
|
||||
private String fileDir;
|
||||
|
||||
@Override
|
||||
protected ActivityRecordVideoBinding getViewBinding() {
|
||||
View decorView = getWindow().getDecorView();
|
||||
int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||
decorView.setSystemUiVisibility(option);
|
||||
return ActivityRecordVideoBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
fileDir = FileUtils.VOID_DIR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readInstanceState(Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start() {
|
||||
|
||||
//设置只能录像或只能拍照或两种都可以(默认两种都可以)
|
||||
viewBinding.jCamera.setFeatures(JCameraView.BUTTON_STATE_BOTH);
|
||||
//设置视频保存路径
|
||||
viewBinding.jCamera.setSaveVideoPath(fileDir);
|
||||
|
||||
viewBinding.jCamera.setErrorLisenter(new ErrorListener() {
|
||||
@Override
|
||||
public void onError() {
|
||||
LogUtils.e("打卡错误");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void AudioPermissionError() {
|
||||
LogUtils.e("没有录音权限");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
viewBinding.jCamera.setCameraOpenOverCallback(new CameraInterface.CameraOpenOverCallback() {
|
||||
@Override
|
||||
public void cameraHasOpened() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
viewBinding.jCamera.cameraHasOpened();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cameraHasOpened(boolean isBackCamera) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
viewBinding.jCamera.cameraHasOpened(isBackCamera);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
//JCameraView监听
|
||||
viewBinding.jCamera.setJCameraLisenter(new JCameraListener() {
|
||||
@Override
|
||||
public void captureSuccess(Bitmap bitmap) {
|
||||
//获取图片bitmap
|
||||
LogUtils.d("拍照成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordSuccess(String url, Bitmap firstFrame, long duration) {
|
||||
LogUtils.d("视频保存成功", url);
|
||||
// /storage/emulated/0/Android/data/com.ruansee.macall.synthesisfight/Void//video_1750677532408.mp4
|
||||
File file = new File(url);
|
||||
if (file.exists()) {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("filePath", file.getAbsolutePath());
|
||||
intent.putExtra("type", "video");
|
||||
intent.putExtra("duration", duration);
|
||||
setResult(Activity.RESULT_OK, intent);
|
||||
finish();
|
||||
} else {
|
||||
ToastUtil.centered(getContext(), "视频保存失败!");
|
||||
viewBinding.jCamera.againPreviewShooting();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return System.currentTimeMillis() + ".mp4";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
viewBinding.jCamera.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
viewBinding.jCamera.onPause();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -12,6 +12,8 @@ import com.rs.macall.androidx.basemodel.callback.PermissionListener;
|
|||
import com.rs.macall.androidx.basemodel.utils.HandlerUtils;
|
||||
import com.ruansee.macall.testwebview.app.RuanseeApp;
|
||||
import com.ruansee.macall.testwebview.databinding.ActivityStartBinding;
|
||||
import com.ruansee.macall.testwebview.db.DatabaseHelp;
|
||||
import com.ruansee.macall.testwebview.utils.FileUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -23,6 +25,7 @@ public class StartActivity extends BaseViewBindActivity<ActivityStartBinding> im
|
|||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.CAMERA,
|
||||
Manifest.permission.RECORD_AUDIO,
|
||||
Manifest.permission.ACCESS_NETWORK_STATE};
|
||||
|
||||
@Override
|
||||
|
|
@ -70,8 +73,11 @@ public class StartActivity extends BaseViewBindActivity<ActivityStartBinding> im
|
|||
}
|
||||
|
||||
private void initPage() {
|
||||
FileUtils.createFilDir();
|
||||
DatabaseHelp.getInstance(getContext());
|
||||
viewBinding.tvMsg.setText("权限通过,正在验证用户信息...");
|
||||
myHandler.sendEmptyMessageDelayed(1, 1000);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,204 @@
|
|||
package com.ruansee.macall.testwebview.activity;
|
||||
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.MediaStore;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.rs.macall.androidx.basemodel.base.BaseViewBindActivity;
|
||||
|
||||
import com.rs.macall.androidx.basemodel.callback.SimpleListClickListener;
|
||||
import com.rs.macall.androidx.basemodel.utils.DateUitls;
|
||||
import com.rs.macall.androidx.basemodel.utils.HandlerUtils;
|
||||
import com.rs.macall.androidx.basemodel.utils.ToastUtil;
|
||||
import com.ruansee.macall.testwebview.R;
|
||||
import com.ruansee.macall.testwebview.adapter.VideoAdapter;
|
||||
import com.ruansee.macall.testwebview.databinding.ActivityWorkbenchBinding;
|
||||
import com.ruansee.macall.testwebview.db.CacheLogTable;
|
||||
import com.ruansee.macall.testwebview.db.CacheLogTableDao;
|
||||
import com.ruansee.macall.testwebview.db.VideoTable;
|
||||
import com.ruansee.macall.testwebview.db.VideoTableDao;
|
||||
import com.ruansee.macall.testwebview.model.SearchModel;
|
||||
import com.ruansee.macall.testwebview.utils.FileUtils;
|
||||
import com.ruansee.macall.testwebview.utils.UriUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class WorkbenchActivity extends BaseViewBindActivity<ActivityWorkbenchBinding> {
|
||||
private SearchModel searchModel;
|
||||
private String nowDate;
|
||||
private static final int REQUEST_VIDEO_CAPTURE = 1201;
|
||||
private File videoFile;
|
||||
private List<String> videoList;
|
||||
private VideoAdapter adapter;
|
||||
|
||||
private Handler myHandler;
|
||||
private VideoTableDao videoTableDao;
|
||||
|
||||
@Override
|
||||
protected ActivityWorkbenchBinding getViewBinding() {
|
||||
return ActivityWorkbenchBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
viewBinding.rvList.setLayoutManager(new GridLayoutManager(getContext(),2));
|
||||
searchModel = new SearchModel(viewBinding.searchContainer,viewBinding.searchEdit,viewBinding.searchClean);
|
||||
myHandler = HandlerUtils.getActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readInstanceState(Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start() {
|
||||
viewBinding.include.contentTitle.setText("工作台");
|
||||
viewBinding.include.leftImage.setImageDrawable(getDrawables(R.drawable.back_cliener));
|
||||
viewBinding.include.titleleft.setOnClickListener(v -> finish());
|
||||
searchModel.init("请输入搜索内容");
|
||||
nowDate = "data"+DateUitls.date2Str(new Date(),"yyyyMMdd");
|
||||
searchModel.setSearchContentListener(new SearchModel.SearchContentListener() {
|
||||
@Override
|
||||
public void onSearch(String content) {
|
||||
if (nowDate.equals(content)){
|
||||
visibleView(viewBinding.btnAdd);
|
||||
|
||||
getVideoList();
|
||||
viewBinding.btnAdd.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dispatchTakeVideoIntent();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClean() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentUpdate(String content) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// CacheLogTableDao<CacheLogTable> cacheLogTableCacheLogTableDao = new CacheLogTableDao<>(getContext(), CacheLogTable.class);
|
||||
// List<CacheLogTable> cacheLogTables = cacheLogTableCacheLogTableDao.queryAll();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what){
|
||||
case 1:
|
||||
if (videoList!=null&&!videoList.isEmpty()){
|
||||
initData();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void getVideoList() {
|
||||
new Thread(){
|
||||
@Override
|
||||
public void run() {
|
||||
videoList = new ArrayList<>();
|
||||
File file = new File(FileUtils.VOID_DIR);
|
||||
if (file.exists()&&file.isDirectory()){
|
||||
File[] files = file.listFiles();
|
||||
if (files!=null){
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File file1 = files[i];
|
||||
if (file1.getName().endsWith(".mp4")){
|
||||
videoList.add(file1.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
myHandler.sendEmptyMessage(1);
|
||||
}
|
||||
}
|
||||
.start();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
if (adapter == null){
|
||||
adapter = new VideoAdapter(getContext(),videoList);
|
||||
viewBinding.rvList.setAdapter(adapter);
|
||||
adapter.setListClickListener(new SimpleListClickListener() {
|
||||
@Override
|
||||
public void onSingleClick(View v, int pointer) {
|
||||
Intent intent = new Intent(getContext(),PlayVideoActivity.class);
|
||||
intent.putExtra("filePath",adapter.getDataItem(pointer));
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
}else {
|
||||
adapter.upData(videoList);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理返回结果
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
|
||||
// Uri videoUri = data.getData();
|
||||
// videoUri 就是拍摄后的视频文件
|
||||
// String realPathFromUri = UriUtils.getRealPathFromUri(getContext(), videoUri);
|
||||
ToastUtil.centered(getContext(),"保存成功!");
|
||||
saveDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
private void saveDatabase() {
|
||||
VideoTable table = new VideoTable();
|
||||
table.setFileNam(videoFile.getName());
|
||||
table.setFilePath(videoFile.getAbsolutePath());
|
||||
table.setCreateTime(DateUitls.date2Str());
|
||||
if (videoTableDao == null){
|
||||
videoTableDao = new VideoTableDao(getContext(), VideoTable.class);
|
||||
}
|
||||
videoTableDao.create(table);
|
||||
if (adapter!=null){
|
||||
adapter.addItem(0,videoFile.getAbsolutePath());
|
||||
}else {
|
||||
videoList = new ArrayList<>();
|
||||
videoList.add(videoFile.getAbsolutePath());
|
||||
initData();
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchTakeVideoIntent() {
|
||||
Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
|
||||
videoFile = new File(FileUtils.VOID_DIR, System.currentTimeMillis() + ".mp4");
|
||||
Uri uri = UriUtils.getUri(getContext(), videoFile);
|
||||
takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
|
||||
// 0: 后摄像头,1: 前摄像头
|
||||
takeVideoIntent.putExtra("android.intent.extras.CAMERA_FACING", 1);
|
||||
takeVideoIntent.putExtra("android.intent.extras.LENS_FACING_FRONT", 1);
|
||||
takeVideoIntent.putExtra("android.intent.extra.USE_FRONT_CAMERA", true);
|
||||
if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
|
||||
startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package com.ruansee.macall.testwebview.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.MultiTransformation;
|
||||
import com.bumptech.glide.load.resource.bitmap.FitCenter;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.CustomViewTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.rs.macall.androidx.basemodel.base.BaseRecyclerAdapter;
|
||||
import com.rs.macall.androidx.basemodel.utils.DimensionConvert;
|
||||
import com.rs.macall.androidx.basemodel.utils.StringUtil;
|
||||
import com.ruansee.macall.testwebview.R;
|
||||
import com.ruansee.macall.testwebview.databinding.ItemVideoBinding;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/7/5 16:39
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
public class VideoAdapter extends BaseRecyclerAdapter<String,BaseRecyclerAdapter.ViewHolder> {
|
||||
|
||||
public VideoAdapter(Context context, List<String> dataList) {
|
||||
super(context, dataList);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@Override
|
||||
public BaseRecyclerAdapter.ViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
|
||||
View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_video, parent, false);
|
||||
ItemVideoBinding bind = ItemVideoBinding.bind(inflate);
|
||||
return new ViewBindingHolder(bind);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull @NotNull BaseRecyclerAdapter.ViewHolder viewHolder, int position) {
|
||||
if (viewHolder instanceof ViewBindingHolder){
|
||||
ViewBindingHolder<ItemVideoBinding> holder =(ViewBindingHolder<ItemVideoBinding>) viewHolder;
|
||||
setChatVideo(holder.viewBind.chatVideo,getDataItem(position));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置聊天图片
|
||||
*
|
||||
* @param iv 图片控件
|
||||
* @param showPath 本地文件路径
|
||||
*/
|
||||
private void setChatVideo(ImageView iv, String showPath) {
|
||||
RoundedCorners roundedCorners = new RoundedCorners(10);
|
||||
MultiTransformation multiTransformation = new MultiTransformation<>(new FitCenter(), roundedCorners);
|
||||
RequestOptions requestOptions = RequestOptions.bitmapTransform(multiTransformation).frame(100000);
|
||||
|
||||
Glide.with(context)
|
||||
.asBitmap()
|
||||
.load(showPath)
|
||||
.apply(requestOptions)
|
||||
|
||||
.into(new CustomViewTarget<ImageView, Bitmap>(iv) {
|
||||
@Override
|
||||
public void onLoadFailed(@Nullable @org.jetbrains.annotations.Nullable Drawable errorDrawable) {
|
||||
ImageView imageView = getView();
|
||||
Drawable resource = ContextCompat.getDrawable(context, R.drawable.ic_load_imag_eerror);
|
||||
// 这里可以根据 resource 宽高动态设置 imageView 的宽高
|
||||
imageView.setImageDrawable(resource);
|
||||
// 例如,强制最小宽高
|
||||
int minWidth = DimensionConvert.dip2px(context, 100); // px
|
||||
int minHeight = DimensionConvert.dip2px(context, 100); // px
|
||||
ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
|
||||
layoutParams.width = Math.max(resource.getIntrinsicWidth(), minWidth);
|
||||
layoutParams.height = Math.max(resource.getIntrinsicHeight(), minHeight);
|
||||
imageView.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResourceReady(@NonNull @NotNull Bitmap resource, @Nullable @org.jetbrains.annotations.Nullable Transition<? super Bitmap> transition) {
|
||||
ImageView imageView = getView();
|
||||
// 这里可以根据 resource 宽高动态设置 imageView 的宽高
|
||||
imageView.setImageBitmap(resource);
|
||||
|
||||
// 例如,强制最小宽高
|
||||
int minWidth = DimensionConvert.dip2px(context, 130); // px
|
||||
ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
|
||||
layoutParams.width = Math.max(resource.getWidth(), minWidth);
|
||||
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
imageView.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResourceCleared(@Nullable @org.jetbrains.annotations.Nullable Drawable placeholder) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.ruansee.macall.testwebview.app;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/7/4 17:54
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
public abstract class ContinuouslyClickListener implements View.OnClickListener {
|
||||
|
||||
private long mLastClickTime;
|
||||
private long timeInterval = 1000L;
|
||||
private int clickNum = 0;
|
||||
private final int maxClickNum=10;
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
long nowTime = System.currentTimeMillis();
|
||||
// LogUtils.w("点击","nowTime="+nowTime+ " ;mLastClickTime = "+mLastClickTime+" ; 差值="+(nowTime - mLastClickTime));
|
||||
if (nowTime - mLastClickTime > timeInterval) {
|
||||
// 单次点击事件
|
||||
onSingleClick(v);
|
||||
clickNum=1;
|
||||
mLastClickTime = nowTime;
|
||||
} else {
|
||||
mLastClickTime = nowTime;
|
||||
// 快速点击事件
|
||||
if (clickNum == maxClickNum){
|
||||
clickNum = 0;
|
||||
onFastClick(v);
|
||||
}else {
|
||||
clickNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void onSingleClick(View v){}
|
||||
public void onFastClick(View v){}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.ruansee.macall.testwebview.app;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/5/23 19:49
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
public abstract class SimpleTextWatcher implements TextWatcher {
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
package com.ruansee.macall.testwebview.db;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/7/5 9:55
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
@DatabaseTable(tableName = "T_CacheLog")
|
||||
public class CacheLogTable {
|
||||
/*因为库里只缓存最后一个人员的信息 ,故 id 固定为1 所有 插入均为 update */
|
||||
@DatabaseField(generatedId = true)
|
||||
private long id = 1;
|
||||
@DatabaseField(columnName = "userName")
|
||||
private String userName;
|
||||
|
||||
@DatabaseField(columnName = "userCode")
|
||||
private String userCode;
|
||||
@DatabaseField(columnName = "deptCode")
|
||||
private String deptCode;
|
||||
@DatabaseField(columnName = "idCardNum")
|
||||
private String idCardNum;
|
||||
@DatabaseField(columnName = "deptName")
|
||||
private String deptName;
|
||||
@DatabaseField(columnName = "appUrl")
|
||||
private String appUrl;
|
||||
@DatabaseField(columnName = "appName")
|
||||
private String appName;
|
||||
|
||||
@DatabaseField(columnName = "clientId")
|
||||
private String clientId;
|
||||
|
||||
@DatabaseField(columnName = "clientSecret")
|
||||
private String clientSecret;
|
||||
|
||||
@DatabaseField(columnName = "operate")
|
||||
private String operate;
|
||||
|
||||
@DatabaseField(columnName = "time")
|
||||
private String time;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserCode() {
|
||||
return userCode;
|
||||
}
|
||||
|
||||
public void setUserCode(String userCode) {
|
||||
this.userCode = userCode;
|
||||
}
|
||||
|
||||
public String getDeptCode() {
|
||||
return deptCode;
|
||||
}
|
||||
|
||||
public void setDeptCode(String deptCode) {
|
||||
this.deptCode = deptCode;
|
||||
}
|
||||
|
||||
public String getIdCardNum() {
|
||||
return idCardNum;
|
||||
}
|
||||
|
||||
public void setIdCardNum(String idCardNum) {
|
||||
this.idCardNum = idCardNum;
|
||||
}
|
||||
|
||||
public String getDeptName() {
|
||||
return deptName;
|
||||
}
|
||||
|
||||
public void setDeptName(String deptName) {
|
||||
this.deptName = deptName;
|
||||
}
|
||||
|
||||
public String getAppUrl() {
|
||||
return appUrl;
|
||||
}
|
||||
|
||||
public void setAppUrl(String appUrl) {
|
||||
this.appUrl = appUrl;
|
||||
}
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public void setAppName(String appName) {
|
||||
this.appName = appName;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
this.clientSecret = clientSecret;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(String time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getOperate() {
|
||||
return operate;
|
||||
}
|
||||
|
||||
public void setOperate(String operate) {
|
||||
this.operate = operate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
package com.ruansee.macall.testwebview.db;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.SQLException;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/7/5 10:59
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
public class CacheLogTableDao {
|
||||
// ORMLite提供的DAO类对象,第一个泛型是要操作的数据表映射成的实体类;第二个泛型是这个实体类中ID的数据类型
|
||||
protected Dao<CacheLogTable, Integer> dao;
|
||||
|
||||
public CacheLogTableDao(Context context, Class<CacheLogTable> tClass) {
|
||||
try {
|
||||
this.dao = DatabaseHelp.getInstance(context).getDao(tClass);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建数据
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void create(CacheLogTable data) {
|
||||
try {
|
||||
dao.createOrUpdate(data);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建数据集合
|
||||
*
|
||||
* @param datas
|
||||
*/
|
||||
public void createList(List<CacheLogTable> datas) {
|
||||
try {
|
||||
dao.create(datas);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向user表中添加一条数据
|
||||
* <p>
|
||||
* create:插入一条数据或集合
|
||||
* <p>
|
||||
* createIfNotExists:如果不存在则插入
|
||||
* <p>
|
||||
* createOrUpdate:如果指定id则更新
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void insert(CacheLogTable data) {
|
||||
try {
|
||||
dao.createIfNotExists(data);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 通过id删除指定数据
|
||||
public void delete(int id) {
|
||||
try {
|
||||
dao.deleteById(id);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 删除表中的一条数据
|
||||
public void delete(CacheLogTable data) {
|
||||
try {
|
||||
dao.delete(data);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 删除数据集合
|
||||
public void deleteList(List<CacheLogTable> datas) {
|
||||
try {
|
||||
dao.delete(datas);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//清空数据
|
||||
public void deleteAll() {
|
||||
try {
|
||||
dao.delete(dao.queryForAll());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 修改表中的一条数据
|
||||
public void update(CacheLogTable data) {
|
||||
try {
|
||||
dao.update(data);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 查询表中的所有数据
|
||||
public List<CacheLogTable> queryAll() {
|
||||
List<CacheLogTable> users = null;
|
||||
try {
|
||||
users = dao.queryForAll();
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
// 根据ID取出用户信息
|
||||
public CacheLogTable queryById(int id) {
|
||||
CacheLogTable user = null;
|
||||
try {
|
||||
user = dao.queryForId(id);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
// 单纯分页查询
|
||||
public List<CacheLogTable> queryList(long page, long pageSize) {
|
||||
try {
|
||||
long pages = (long) (page * pageSize - pageSize);
|
||||
return dao.queryBuilder().offset(pages < 0 ? 0 : pages).limit(pageSize).query();
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 通过条件查询集合(例如:通过messageId和title)
|
||||
public long queryCount() {
|
||||
try {
|
||||
return dao.queryBuilder().countOf();
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.ruansee.macall.testwebview.db;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.support.ConnectionSource;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
import com.ruansee.macall.testwebview.utils.FileUtils;
|
||||
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/7/5 10:02
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
public final class DatabaseHelp extends OrmLiteSqliteOpenHelper {
|
||||
|
||||
// 数据库名称
|
||||
public static final String DATABASE_NAME = FileUtils.DB_DIR+"rcwhy.db";
|
||||
|
||||
// 本类的单例实例
|
||||
private static DatabaseHelp instance;
|
||||
// 存储APP中所有的DAO对象的Map集合
|
||||
@SuppressLint("NewApi")
|
||||
private ArrayMap<String, Dao> daos = new ArrayMap<>();
|
||||
|
||||
// 私有的构造方法
|
||||
private DatabaseHelp(Context context) {
|
||||
super(context, DATABASE_NAME, null, 1);
|
||||
}
|
||||
|
||||
|
||||
// 获取本类单例对象的方法
|
||||
public static synchronized DatabaseHelp getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
synchronized (DatabaseHelp.class) {
|
||||
if (instance == null) {
|
||||
instance = new DatabaseHelp(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// 根据传入的DAO的路径获取到这个DAO的单例对象(要么从daos这个Map中获取,要么新创建一个并存入daos)
|
||||
public synchronized Dao getDao(Class clazz) throws SQLException, java.sql.SQLException {
|
||||
Dao dao = null;
|
||||
String className = clazz.getSimpleName();
|
||||
if (daos.containsKey(className)) {
|
||||
dao = daos.get(className);
|
||||
}
|
||||
if (dao == null) {
|
||||
dao = super.getDao(clazz);
|
||||
daos.put(className, dao);
|
||||
}
|
||||
return dao;
|
||||
}
|
||||
|
||||
// 释放资源
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
for (String key : daos.keySet()) {
|
||||
Dao dao = daos.get(key);
|
||||
dao = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
|
||||
try {
|
||||
TableUtils.createTable(connectionSource, CacheLogTable.class);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.ruansee.macall.testwebview.db;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/7/5 16:16
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
@DatabaseTable(tableName = "T_Video")
|
||||
public class VideoTable {
|
||||
|
||||
@DatabaseField(generatedId = true)
|
||||
private long id;
|
||||
|
||||
@DatabaseField(columnName = "fileName")
|
||||
private String fileNam;
|
||||
|
||||
@DatabaseField(columnName = "filePath")
|
||||
private String filePath;
|
||||
|
||||
@DatabaseField(columnName = "createTime")
|
||||
private String createTime;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFileNam() {
|
||||
return fileNam;
|
||||
}
|
||||
|
||||
public void setFileNam(String fileNam) {
|
||||
this.fileNam = fileNam;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public String getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(String createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
package com.ruansee.macall.testwebview.db;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.SQLException;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/7/5 16:32
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
public class VideoTableDao {
|
||||
// ORMLite提供的DAO类对象,第一个泛型是要操作的数据表映射成的实体类;第二个泛型是这个实体类中ID的数据类型
|
||||
protected Dao<VideoTable, Integer> dao;
|
||||
|
||||
public VideoTableDao(Context context, Class<VideoTable> tClass) {
|
||||
try {
|
||||
this.dao = DatabaseHelp.getInstance(context).getDao(tClass);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建数据
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void create(VideoTable data) {
|
||||
try {
|
||||
dao.createOrUpdate(data);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建数据集合
|
||||
*
|
||||
* @param datas
|
||||
*/
|
||||
public void createList(List<VideoTable> datas) {
|
||||
try {
|
||||
dao.create(datas);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向user表中添加一条数据
|
||||
* <p>
|
||||
* create:插入一条数据或集合
|
||||
* <p>
|
||||
* createIfNotExists:如果不存在则插入
|
||||
* <p>
|
||||
* createOrUpdate:如果指定id则更新
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void insert(VideoTable data) {
|
||||
try {
|
||||
dao.createIfNotExists(data);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 通过id删除指定数据
|
||||
public void delete(int id) {
|
||||
try {
|
||||
dao.deleteById(id);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 删除表中的一条数据
|
||||
public void delete(VideoTable data) {
|
||||
try {
|
||||
dao.delete(data);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 删除数据集合
|
||||
public void deleteList(List<VideoTable> datas) {
|
||||
try {
|
||||
dao.delete(datas);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//清空数据
|
||||
public void deleteAll() {
|
||||
try {
|
||||
dao.delete(dao.queryForAll());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 修改表中的一条数据
|
||||
public void update(VideoTable data) {
|
||||
try {
|
||||
dao.update(data);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 查询表中的所有数据
|
||||
public List<VideoTable> queryAll() {
|
||||
List<VideoTable> users = null;
|
||||
try {
|
||||
users = dao.queryForAll();
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
// 根据ID取出用户信息
|
||||
public VideoTable queryById(int id) {
|
||||
VideoTable user = null;
|
||||
try {
|
||||
user = dao.queryForId(id);
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
// 单纯分页查询
|
||||
public List<VideoTable> queryList(long page, long pageSize) {
|
||||
try {
|
||||
long pages = (long) (page * pageSize - pageSize);
|
||||
return dao.queryBuilder().offset(pages < 0 ? 0 : pages).limit(pageSize).query();
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 通过条件查询集合(例如:通过messageId和title)
|
||||
public long queryCount() {
|
||||
try {
|
||||
return dao.queryBuilder().countOf();
|
||||
} catch (SQLException | java.sql.SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
package com.ruansee.macall.testwebview.model;
|
||||
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.jzvd.JZMediaInterface;
|
||||
import cn.jzvd.Jzvd;
|
||||
import tv.danmaku.ijk.media.player.IMediaPlayer;
|
||||
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
|
||||
import tv.danmaku.ijk.media.player.IjkTimedText;
|
||||
|
||||
/**
|
||||
*
|
||||
* Created by Nathen on 2017/11/18.
|
||||
*/
|
||||
|
||||
public class JZMediaIjk extends JZMediaInterface implements IMediaPlayer.OnPreparedListener, IMediaPlayer.OnVideoSizeChangedListener, IMediaPlayer.OnCompletionListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnInfoListener, IMediaPlayer.OnBufferingUpdateListener, IMediaPlayer.OnSeekCompleteListener, IMediaPlayer.OnTimedTextListener {
|
||||
IjkMediaPlayer ijkMediaPlayer;
|
||||
|
||||
public JZMediaIjk(Jzvd jzvd) {
|
||||
super(jzvd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (ijkMediaPlayer != null) ijkMediaPlayer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare() {
|
||||
|
||||
release();
|
||||
mMediaHandlerThread = new HandlerThread("JZVD");
|
||||
mMediaHandlerThread.start();
|
||||
mMediaHandler = new Handler(mMediaHandlerThread.getLooper());//主线程还是非主线程,就在这里
|
||||
handler = new Handler();
|
||||
|
||||
mMediaHandler.post(() -> {
|
||||
|
||||
ijkMediaPlayer = new IjkMediaPlayer();
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 1024 * 1024);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);
|
||||
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
|
||||
|
||||
|
||||
ijkMediaPlayer.setOnPreparedListener(JZMediaIjk.this);
|
||||
ijkMediaPlayer.setOnVideoSizeChangedListener(JZMediaIjk.this);
|
||||
ijkMediaPlayer.setOnCompletionListener(JZMediaIjk.this);
|
||||
ijkMediaPlayer.setOnErrorListener(JZMediaIjk.this);
|
||||
ijkMediaPlayer.setOnInfoListener(JZMediaIjk.this);
|
||||
ijkMediaPlayer.setOnBufferingUpdateListener(JZMediaIjk.this);
|
||||
ijkMediaPlayer.setOnSeekCompleteListener(JZMediaIjk.this);
|
||||
ijkMediaPlayer.setOnTimedTextListener(JZMediaIjk.this);
|
||||
|
||||
try {
|
||||
ijkMediaPlayer.setDataSource(jzvd.jzDataSource.getCurrentUrl().toString());
|
||||
ijkMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
ijkMediaPlayer.setScreenOnWhilePlaying(true);
|
||||
ijkMediaPlayer.prepareAsync();
|
||||
|
||||
ijkMediaPlayer.setSurface(new Surface(jzvd.textureView.getSurfaceTexture()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
ijkMediaPlayer.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
return ijkMediaPlayer.isPlaying();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekTo(long time) {
|
||||
ijkMediaPlayer.seekTo(time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if (mMediaHandler != null && mMediaHandlerThread != null && ijkMediaPlayer != null) {//不知道有没有妖孽
|
||||
HandlerThread tmpHandlerThread = mMediaHandlerThread;
|
||||
IjkMediaPlayer tmpMediaPlayer = ijkMediaPlayer;
|
||||
JZMediaInterface.SAVED_SURFACE = null;
|
||||
|
||||
mMediaHandler.post(() -> {
|
||||
tmpMediaPlayer.setSurface(null);
|
||||
tmpMediaPlayer.release();
|
||||
tmpHandlerThread.quit();
|
||||
});
|
||||
ijkMediaPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCurrentPosition() {
|
||||
return ijkMediaPlayer.getCurrentPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return ijkMediaPlayer.getDuration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolume(float leftVolume, float rightVolume) {
|
||||
ijkMediaPlayer.setVolume(leftVolume, rightVolume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeed(float speed) {
|
||||
ijkMediaPlayer.setSpeed(speed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepared(IMediaPlayer iMediaPlayer) {
|
||||
handler.post(() -> jzvd.onPrepared());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int i, int i1, int i2, int i3) {
|
||||
handler.post(() -> jzvd.onVideoSizeChanged(iMediaPlayer.getVideoWidth(), iMediaPlayer.getVideoHeight()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onError(IMediaPlayer iMediaPlayer, final int what, final int extra) {
|
||||
handler.post(() -> jzvd.onError(what, extra));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInfo(IMediaPlayer iMediaPlayer, final int what, final int extra) {
|
||||
handler.post(() -> jzvd.onInfo(what, extra));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(IMediaPlayer iMediaPlayer, final int percent) {
|
||||
handler.post(() -> jzvd.setBufferProgress(percent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSeekComplete(IMediaPlayer iMediaPlayer) {
|
||||
handler.post(() -> jzvd.onSeekComplete());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimedText(IMediaPlayer iMediaPlayer, IjkTimedText ijkTimedText) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSurface(Surface surface) {
|
||||
ijkMediaPlayer.setSurface(surface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
|
||||
if (SAVED_SURFACE == null) {
|
||||
SAVED_SURFACE = surface;
|
||||
prepare();
|
||||
} else {
|
||||
jzvd.textureView.setSurfaceTexture(SAVED_SURFACE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompletion(IMediaPlayer iMediaPlayer) {
|
||||
handler.post(() -> jzvd.onAutoCompletion());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
package com.ruansee.macall.testwebview.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
import com.ruansee.macall.testwebview.R;
|
||||
|
||||
import cn.jzvd.JzvdStd;
|
||||
import tv.danmaku.ijk.media.player.IMediaPlayer;
|
||||
|
||||
/**
|
||||
* 这里可以监听到视频播放的生命周期和播放状态
|
||||
* 所有关于视频的逻辑都应该写在这里
|
||||
* Created by Nathen on 2017/7/2.
|
||||
*/
|
||||
public class MyJzvdStd extends JzvdStd {
|
||||
public MyJzvdStd(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MyJzvdStd(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Context context) {
|
||||
super.init(context);
|
||||
backButton.setVisibility(GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
super.onClick(v);
|
||||
int i = v.getId();
|
||||
if (i == R.id.fullscreen) {
|
||||
Log.i(TAG, "onClick: fullscreen button");
|
||||
} else if (i == R.id.start) {
|
||||
Log.i(TAG, "onClick: start button");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
super.onTouch(v, event);
|
||||
int id = v.getId();
|
||||
if (id == R.id.surface_container) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (mChangePosition) {
|
||||
Log.i(TAG, "Touch screen seek position");
|
||||
}
|
||||
if (mChangeVolume) {
|
||||
Log.i(TAG, "Touch screen change volume");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return R.layout.jz_layout_std;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startVideo() {
|
||||
super.startVideo();
|
||||
Log.i(TAG, "startVideo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
super.onStopTrackingTouch(seekBar);
|
||||
Log.i(TAG, "Seek position ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gotoScreenFullscreen() {
|
||||
super.gotoScreenFullscreen();
|
||||
Log.i(TAG, "goto Fullscreen");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gotoScreenNormal() {
|
||||
super.gotoScreenNormal();
|
||||
Log.i(TAG, "quit Fullscreen");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autoFullscreen(float x) {
|
||||
super.autoFullscreen(x);
|
||||
Log.i(TAG, "auto Fullscreen");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickUiToggle() {
|
||||
super.onClickUiToggle();
|
||||
Log.i(TAG, "click blank");
|
||||
}
|
||||
|
||||
//onState 代表了播放器引擎的回调,播放视频各个过程的状态的回调
|
||||
@Override
|
||||
public void onStateNormal() {
|
||||
super.onStateNormal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatePreparing() {
|
||||
super.onStatePreparing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatePlaying() {
|
||||
super.onStatePlaying();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatePause() {
|
||||
super.onStatePause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateError() {
|
||||
super.onStateError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateAutoComplete() {
|
||||
super.onStateAutoComplete();
|
||||
Log.i(TAG, "Auto complete");
|
||||
}
|
||||
|
||||
//changeUiTo 真能能修改ui的方法
|
||||
@Override
|
||||
public void changeUiToNormal() {
|
||||
super.changeUiToNormal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeUiToPreparing() {
|
||||
super.changeUiToPreparing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeUiToPlayingShow() {
|
||||
super.changeUiToPlayingShow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeUiToPlayingClear() {
|
||||
super.changeUiToPlayingClear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeUiToPauseShow() {
|
||||
super.changeUiToPauseShow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeUiToPauseClear() {
|
||||
super.changeUiToPauseClear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeUiToComplete() {
|
||||
super.changeUiToComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeUiToError() {
|
||||
super.changeUiToError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInfo(int what, int extra) {
|
||||
super.onInfo(what, extra);
|
||||
if(what==IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED){
|
||||
//这里返回了视频的旋转角度,根据角度旋转视频到正确角度
|
||||
textureView.setRotation(extra);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int what, int extra) {
|
||||
super.onError(what, extra);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package com.ruansee.macall.testwebview.model;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
|
||||
import com.rs.macall.androidx.basemodel.callback.CustomClickListener;
|
||||
import com.rs.macall.androidx.basemodel.utils.StringUtil;
|
||||
import com.ruansee.macall.testwebview.app.SimpleTextWatcher;
|
||||
|
||||
/**
|
||||
* created by: Macall
|
||||
* create time: 2025/5/21 14:28
|
||||
* copyright: @ruansee.com
|
||||
* Describe:
|
||||
*/
|
||||
public class SearchModel {
|
||||
private LinearLayout search_container;
|
||||
private EditText search_edit;
|
||||
private ImageView search_clean;
|
||||
private SearchContentListener searchContentListener;
|
||||
|
||||
public void setSearchContentListener(SearchContentListener searchContentListener) {
|
||||
this.searchContentListener = searchContentListener;
|
||||
}
|
||||
|
||||
public SearchModel(LinearLayout search_container, EditText search_edit, ImageView search_clean) {
|
||||
this.search_container = search_container;
|
||||
this.search_edit = search_edit;
|
||||
this.search_clean = search_clean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置输入背景框
|
||||
* @param layoutBackground
|
||||
*/
|
||||
public void layoutBackground(@DrawableRes int layoutBackground){
|
||||
search_container.setBackgroundResource(layoutBackground);
|
||||
}
|
||||
|
||||
public void init(String hintStr) {
|
||||
search_clean.setVisibility(View.GONE);
|
||||
search_clean.setOnClickListener(new CustomClickListener() {
|
||||
@Override
|
||||
public void onSingleClick(View v) {
|
||||
search_edit.setText("");
|
||||
if (searchContentListener != null) {
|
||||
searchContentListener.onClean();
|
||||
}
|
||||
}
|
||||
});
|
||||
search_edit.setHint(StringUtil.get(hintStr, "搜索"));
|
||||
search_edit.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
|
||||
search_edit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
if (searchContentListener != null) {
|
||||
searchContentListener.onSearch(search_edit.getText().toString());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
search_edit.addTextChangedListener(new SimpleTextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (s.length() >= 1) {
|
||||
search_clean.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
search_clean.setVisibility(View.GONE);
|
||||
if (searchContentListener != null) {
|
||||
searchContentListener.onClean();
|
||||
}
|
||||
}
|
||||
if (searchContentListener != null) {
|
||||
searchContentListener.onContentUpdate(s.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改提示词
|
||||
*
|
||||
* @param hintStr
|
||||
*/
|
||||
public void updateHint(String hintStr) {
|
||||
search_edit.setHint(StringUtil.get(hintStr, "搜索"));
|
||||
}
|
||||
|
||||
|
||||
public interface SearchContentListener {
|
||||
/**
|
||||
* 按下搜索按钮时触发
|
||||
*
|
||||
* @param content 输入的内容
|
||||
*/
|
||||
void onSearch(String content);
|
||||
|
||||
/**
|
||||
* 点击清空按钮时触发
|
||||
*/
|
||||
void onClean();
|
||||
|
||||
/**
|
||||
* 输入内容发生改变时出发,用于需要实时监听输入内容的场景
|
||||
*
|
||||
* @param content 输入内容
|
||||
*/
|
||||
void onContentUpdate(String content);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +88,36 @@ public class FileUtils {
|
|||
return filePath;
|
||||
}
|
||||
|
||||
public static void createFilDir(){
|
||||
File file = new File(filePath);
|
||||
if (!file.exists()){
|
||||
file.mkdirs();
|
||||
}
|
||||
file = new File(DOWNLOADS_DIR);
|
||||
if (!file.exists()){
|
||||
file.mkdirs();
|
||||
}
|
||||
file = new File(IMAGE_DIR);
|
||||
if (!file.exists()){
|
||||
file.mkdirs();
|
||||
}
|
||||
file = new File(VOID_DIR);
|
||||
if (!file.exists()){
|
||||
file.mkdirs();
|
||||
}
|
||||
file = new File(FILE_DIR);
|
||||
if (!file.exists()){
|
||||
file.mkdirs();
|
||||
}
|
||||
file = new File(DB_DIR);
|
||||
if (!file.exists()){
|
||||
file.mkdirs();
|
||||
}file = new File(LOG_DIR);
|
||||
if (!file.exists()){
|
||||
file.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getPhotoName() {
|
||||
return System.currentTimeMillis() + ".jpg";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M9,3L7.17,5L4,5c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,7c0,-1.1 -0.9,-2 -2,-2h-3.17L15,3L9,3zM12,18c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,17l1.25,-2.75L16,13l-2.75,-1.25L12,9l-1.25,2.75L8,13l2.75,1.25z"/>
|
||||
</vector>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/colorGrey1" />
|
||||
<stroke android:width="1dp" android:color="@color/colorBluen2" />
|
||||
<corners android:radius="@dimen/dp5" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_focused="false">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/colorWhite" />
|
||||
<stroke android:width="1dp" android:color="@color/colorGrey2" />
|
||||
<corners android:radius="@dimen/dp5" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@drawable/icon_add_def" android:state_pressed="false"/>
|
||||
<item android:drawable="@drawable/icon_add_sel" android:state_pressed="true"/>
|
||||
|
||||
|
||||
</selector>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorGrey2"
|
||||
tools:context=".activity.PlayVideoActivity">
|
||||
|
||||
<com.ruansee.macall.testwebview.model.MyJzvdStd
|
||||
android:id="@+id/jz_video"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activity.RecordVideoActivity">
|
||||
|
||||
<com.ycgis.macall.jcamera.JCameraView
|
||||
android:id="@+id/j_camera"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:duration_max="300000"
|
||||
app:camera_position="rearMounted"
|
||||
app:camera_switching="true"
|
||||
app:iconMargin="20dp"
|
||||
app:iconSize="30dp"
|
||||
app:iconSrc="@drawable/ic_camera_enhance_black_24dp"
|
||||
/>
|
||||
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activity.WorkbenchActivity">
|
||||
|
||||
<include
|
||||
android:id="@+id/app_title"
|
||||
layout="@layout/app_base_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/search_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp42"
|
||||
android:layout_marginHorizontal="@dimen/dp15"
|
||||
android:layout_marginVertical="@dimen/dp8"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:background="@drawable/edit_background"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/app_title">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_icon"
|
||||
android:layout_width="@dimen/dp25"
|
||||
android:layout_height="@dimen/dp25"
|
||||
android:layout_marginStart="@dimen/dp5"
|
||||
android:src="@drawable/icon_search" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_edit"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginHorizontal="@dimen/dp5"
|
||||
android:layout_weight="1"
|
||||
android:background="@null"
|
||||
android:hint="搜索"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/colorGrey8"
|
||||
android:textColorHint="@color/colorGrey6"
|
||||
android:textSize="@dimen/sp16" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_clean"
|
||||
android:layout_width="@dimen/dp30"
|
||||
android:layout_height="@dimen/dp25"
|
||||
android:paddingEnd="@dimen/dp5"
|
||||
android:src="@drawable/icon_search_delete" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search_container" />
|
||||
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btn_add"
|
||||
android:layout_width="@dimen/dp68"
|
||||
android:layout_height="@dimen/dp68"
|
||||
android:background="@null"
|
||||
android:src="@drawable/icon_add"
|
||||
android:layout_marginEnd="@dimen/dp60"
|
||||
android:layout_marginBottom="@dimen/dp60"
|
||||
android:scaleType="fitXY"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/dp180"
|
||||
android:layout_height="@dimen/dp200"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/chat_video"
|
||||
android:layout_width="@dimen/dp100"
|
||||
android:layout_height="@dimen/dp100"
|
||||
android:adjustViewBounds="true"
|
||||
android:gravity="left|center"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/icon_login2" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/chat_play"
|
||||
android:layout_width="@dimen/dp38"
|
||||
android:layout_height="@dimen/dp38"
|
||||
android:src="@drawable/icon_play"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/chat_video_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:text="0:32"
|
||||
android:textColor="@color/colorGrey4"
|
||||
android:textSize="@dimen/sp10"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/search_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp42"
|
||||
android:layout_marginHorizontal="@dimen/dp15"
|
||||
android:layout_marginVertical="@dimen/dp8"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:background="@drawable/edit_background"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_icon"
|
||||
android:layout_width="@dimen/dp25"
|
||||
android:layout_height="@dimen/dp25"
|
||||
android:layout_marginStart="@dimen/dp5"
|
||||
android:src="@drawable/icon_search" />
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_edit"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginHorizontal="@dimen/dp5"
|
||||
android:layout_weight="1"
|
||||
android:background="@null"
|
||||
android:hint="搜索"
|
||||
android:inputType="text"
|
||||
android:imeOptions="actionSearch"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/colorGrey8"
|
||||
android:textColorHint="@color/colorGrey6"
|
||||
android:textSize="@dimen/sp16" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_clean"
|
||||
android:layout_width="@dimen/dp30"
|
||||
android:layout_height="@dimen/dp25"
|
||||
android:paddingEnd="@dimen/dp5"
|
||||
android:src="@drawable/icon_search_delete" />
|
||||
|
||||
</LinearLayout>
|
||||
Loading…
Reference in New Issue