同步操作将从 ichtj/BaseIotUtils 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://www.jitpack.io' }
}
}
dependencies {
//socket通信 tcp/udp工具类 使用方式请参考app module中的代码
implementation 'com.chtj.base_socket:base_socket:1.0.2'
}
dependencies {
//以宽高进行屏幕适配,shell,网络判断等多种工具类以及后台存活串口封装等
implementation 'com.chtj.base_iotutils:base_iotutils:1.2.3'
}
//BaseUdpSocket | BaseTcpSocket tcp|udp 使用方式类似
BaseTcpSocket baseTcpSocket = new BaseTcpSocket(192.168.1.100,8080, 5000);
//监听回调
baseTcpSocket.setSocketListener(new ISocketListener()...);
//开启连接
baseTcpSocket.connect(this);
//发送数据
baseTcpSocket.send("hello world!".getBytes());
//关闭连接
baseTcpSocket.close();
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
//1.1.6 之后与之前有较大改动
//需要在 Application 的 onCreate() 中调用一次 BaseIotTools.instance()....
//1080,1920是为了适配而去设置相关的值
//设置宽度|高度布局尺寸 layout 布局文件以pt为单位 setBaseScreenParam(1080,1920,true)
BaseIotUtils.instance().
setBaseScreenParam(1080,1920,true).
setCreenType(SCREEN_TYPE.WIDTH).//按照宽度适配
create(getApplication());
//别忘了在 Manifest 中通过 android:name 使用这个自定义的 Application.
}
}
进制转换类 | HexUtils
设备相关 | DeviceUtils
键盘相关 | KeyBoardUtils
网络判断 | NetWorkUtils
adb命令工具类 | ShellUtils
ShareProfrence工具类 | SPUtils
Toast工具类 | ToastUtil
后台服务类 保活 | AbsWorkService
App相关信息工具类 | AppUtils
屏幕适配相关 | AdaptScreenUtils
串口工具 | SerialPort | SerialPortFinder
日志管理 | KLog
文件操作 | FileUtil
事件管理 | RxBus
文件下载 | DownLoadManager
-可在app Model中找到使用示例
//downloadUrl 文件下载地址
//destFileDir 存放地址
//destFileName 文件名称
DownLoadManager.getInstance().load(downloadUrl, new ProgressCallBack<ResponseBody>(destFileDir, destFileName) {
@Override
public void onStart() {
super.onStart();
}
@Override
public void onSuccess(ResponseBody responseBody) {
ToastUtils.showShort("文件下载完成!");
}
@Override
public void progress(final long progress, final long total) {
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
ToastUtils.showShort("文件下载失败!");
}
});
#串口使用
//初始化串口工具类
SerialPortHelper serialPortHelper=new SerialPortHelper(SerialPortNormalAty.this, comEntity);
//一:获取该android设备下的所有串口地址
//二:波特率请根据实际需要添加,位置在R.array.burate文件下
SerialPortFinder mSerialPortFinder = new SerialPortFinder();
String[] entryValues = mSerialPortFinder.getAllDevicesPath();
//三:配置参数
//参数设置
List<Integer> flagFilterList = new ArrayList<>();
flagFilterList.add(FlagManager.FLAG_CHECK_UPDATE);
//数据头(包头) 主要用于判断读取的命令是否符合协议
List<Byte> headDataList = new ArrayList<>();
headDataList.add((byte) 0xAA);
headDataList.add((byte) 0x55);
//指令标识 主要用于判断读取的命令是否符合协议
List<Byte> instructionList = new ArrayList<>();
instructionList.add((byte) -96);//A3 自检
instructionList.add((byte) -95);//A2 数据写入
instructionList.add((byte) -94);//A1 加入升级
instructionList.add((byte) -93);//A0 检查升级
//①未开启心跳包
//ComEntity comEntity=new ComEntity(com,baudrate,6000,3,headDataList,3,2,6,5,instructionList,flagFilterList);
//②心跳包参数设置 默认用某一条命令周期性的去获取设备返回的消息
//主要判断是否连接正常
HeartBeatEntity heartBeatEntity = new HeartBeatEntity(new byte[]{(byte) 0xAA, 0x55, 00, 0, 0x01, (byte) 0xA0, (byte) 0xBF}, FlagManager.FLAG_HEARTBEAT, 15 * 1000);
ComEntity comEntity = new ComEntity(
com//串口地址
, baudrate//波特率
, 6000//超时时间
, 3//重试次数
, headDataList//数据头 用于去校验是否正确
, 3//data长度开始的位置 从0开始
, 2//data长度
, 6//其他位的固定长度
, 5//指令开始的位置 从0开始
, instructionList//指令集合
, heartBeatEntity//心跳检测参数
, flagFilterList//写命令时如果当前flag的命令大于两条 添加进来的不会因为第一条命令执行失败,而不向下执行
);
//初始化数据
serialPortHelper = new SerialPortHelper(SerialPortNormalAty.this, comEntity);
//注册监听
serialPortHelper.setOnComListener(new OnComListener() {
@Override
public void writeCommand(byte[] comm, int flag) {
}
@Override
public void readCommand(byte[] comm, int flag) {
}
@Override
public void writeComplet(int flag) {
}
@Override
public void isReadTimeOut(int flag) {
}
@Override
public void isOpen(boolean isOpen) {
}
@Override
public void comStatus(boolean isNormal) {
}
});
//4:开启串口
serialPortHelper.openSerialPort();
//5:关闭串口
//if (serialPortHelper != null) {
// serialPortHelper.closeSerialPort();
//}
//获得串口地址
SerialPortFinder mSerialPortFinder = new SerialPortFinder();
String[] entryValues = mSerialPortFinder.getAllDevicesPath();
//根据串口地址和波特率开启串口
SerialPort port = null;
try{
port=new SerialPort(new File(entryValues[xxx]), xxx,0);
Log.e(TAG,"开启成功");
}catch(Exception e){
e.printStackTrace();
Log.e(TAG,"errMeg:"+e.getMessage());
}
//写命令
port.write(command);
//读命令
//可根据SerialPortHelper中的readInputStreamData(int flag)方法读取数据,这里是一个一个字节读取
//亦或用port中的read方法一次读取,如果数据量大可能存在粘包
port.read(byte[] buff,int lenght);
//关闭串口
port.close();
使用方式
//初始化后台保活Service
BaseIotUtils.initSerice(TraceServiceImpl.class, BaseIotUtils.DEFAULT_WAKE_UP_INTERVAL);
//开启service
TraceServiceImpl.sShouldStopService = false;
BaseIotUtils.startServiceMayBind(TraceServiceImpl.class);
//关闭service
TraceServiceImpl.stopService();
Android 进程常驻(2)----细数利用android系统机制的保活手段
D-clock / AndroidDaemonService
D-clock :
思路一:API < 18,启动前台Service时直接传入new Notification();
思路二:API >= 18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理;
//启动前台服务而不显示通知的漏洞已在 API Level 25 修复,大快人心!
前台服务相对于后台服务的优势,除了优先级的提升以外,还有一点:
在最近任务列表中划掉卡片时,前台服务不会停止;
(更新:经过测试,发现只是对于AOSP/CM/国际上对Framework层改动较小的Android系统是成立的;EMUI/MIUI等未加入白名单的情况下,划掉卡片,前台服务也会停止;加入白名单后划掉卡片的行为与国际厂商的系统相似。)
而后台服务会停止,并在稍后重新启动(onStartCommand 返回 START_STICKY 时)。
前台服务和后台服务被划掉卡片时,回调的都是 onTaskRemoved 方法。
onDestroy 方法只在 设置 -> 开发者选项 -> 正在运行的服务 里停止服务时才会回调。
CONNECTIVITY_CHANGE, USER_PRESENT, ACTION_POWER_CONNECTED, ACTION_POWER_DISCONNECTED, BOOT_COMPLETED, PACKAGE_ADDED, PACKAGE_REMOVED.
在网络连接改变, 用户屏幕解锁, 电源连接 / 断开, 系统启动完成, 安装 / 卸载软件包时拉起 Service.
Service 内部做了判断,若 Service 已在运行,不会重复启动.
详见上面的 2 个链接。
使用 JobScheduler, Android 系统能自动拉起被 Force Stop 的 Package,而 AlarmManager 无法拉起.
Android 4.4 及以下版本使用 AlarmManager.
测试机型 : 华为 荣耀6 Plus (EMUI 4.0 Android 6.0), 应用未加入白名单.
观察到 :
在未加入白名单的情况下,按Back键回到桌面再锁屏后几秒钟即会杀掉进程;
但是按Home键返回桌面的话,即使锁屏,也不会杀掉进程。
(更新:经过测试,在EMUI系统上,『即使锁屏,也不会杀掉进程』只对App的卡片还在多任务屏幕的第一屏时有效,一旦被挤到第二页及以后,锁屏后几秒钟即会杀掉进程;加入白名单后,回到桌面再锁屏后不会杀进程。)
因此,重写了onBackPressed方法,使其只是返回到桌面,而不是将当前Activity finish/destroy掉。
测试机型 : 红米1S 4G (MIUI 8 Android 4.4.2), 应用未加入白名单.
观察到 :
在未加入白名单的情况下,回到桌面再锁屏后不会杀进程;
但划掉卡片,进程死亡并不再启动;加入白名单后,划掉卡片,服务不会停止,与CM的行为相似。
可以看出,若不想使用Native保活,引导用户加入白名单可能是比较可行的方法。
配合 android.support.v7.AlertDialog 引导用户将 App 加入白名单.
参考了 Poweramp, 启动的前台服务与 UI 运行在同一进程中。
若服务还在运行,就什么也不做;若服务不在运行就拉起来。
开始任务前,先检查磁盘中是否有上次销毁时保存的数据;定期将数据保存到磁盘。
/**
* 是否 任务完成, 不再需要服务运行?
* @return 应当停止服务, true; 应当启动服务, false; 无法判断, null.
*/
Boolean shouldStopService();
/**
* 任务是否正在运行?
* @return 任务正在运行, true; 任务当前不在运行, false; 无法判断, null.
*/
Boolean isWorkRunning();
void startWork();
void stopWork();
//Service.onBind(Intent intent)
@Nullable IBinder onBind(Intent intent, Void unused);
//服务被杀时调用, 可以在这里面保存数据.
void onServiceKilled();
Context.startService(new Intent(Context c, Class<? extends AbsWorkService> serviceClass))
在 ? extends AbsWorkService 中, 添加 stopService()
方法:
1.操作自己维护的 flag, 使 shouldStopService()
返回 true
;
2.调用自己的方法或第三方 SDK 提供的 API, 停止任务;
3.调用 AbsWorkService.cancelJobAlarmSub()
取消 Job / Alarm / Subscription.
需要停止服务时, 调用 ? extends AbsWorkService 上的 stopService()
即可.
以下 API 全部位于 IntentWrapper 中:
List<IntentWrapper> getIntentWrapperList();
//弹出 android.support.v7.AlertDialog, 引导用户将 App 加入白名单.
void whiteListMatters(Activity a, String reason);
//防止华为机型未加入白名单时按返回键回到桌面再锁屏后几秒钟进程被杀.
//重写 MainActivity.onBackPressed(), 只保留对以下 API 的调用.
void onBackPressed(Activity a);
AbsWorkService.cancelJobAlarmSub()
取消定时唤醒的 Job / Alarm / Subscription, 并调用 stopService()
停止服务.详见代码及注释。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。