mirror of
https://github.com/RfidResearchGroup/RFIDtools.git
synced 2026-05-12 11:19:59 -07:00
first commit.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cn.dxl.common">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
|
||||
</provider>
|
||||
|
||||
<!--APP重启服务-->
|
||||
<service
|
||||
android:name="cn.dxl.common.services.RestartService"
|
||||
android:enabled="true"
|
||||
android:process=":restart" />
|
||||
|
||||
<activity android:name="cn.dxl.common.activities.CrashActivity" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,49 @@
|
||||
package cn.dxl.common.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import cn.dxl.common.R;
|
||||
|
||||
|
||||
/**
|
||||
* show throwable!
|
||||
*/
|
||||
public class CrashActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.act_crash_main);
|
||||
|
||||
TextView txtShowMsg = findViewById(R.id.txtView_showMsg);
|
||||
|
||||
//接收意图中序列化过来的Throwable对象
|
||||
Throwable t = (Throwable) getIntent().getSerializableExtra("crash");
|
||||
if (t == null) {
|
||||
Toast.makeText(this, "接收到的异常对象为空!", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append(t.getLocalizedMessage()).append('\n');
|
||||
for (StackTraceElement st : t.getStackTrace()) {
|
||||
msg.append('\n');
|
||||
msg.append("at: ");
|
||||
msg.append(st.toString());
|
||||
}
|
||||
txtShowMsg.setText(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
//终止虚拟机的执行
|
||||
finish();
|
||||
Process.killProcess(Process.myPid());
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.dxl.common.application;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import cn.dxl.common.util.AppUtil;
|
||||
import cn.dxl.common.util.CrashUtil;
|
||||
|
||||
public class App extends Application {
|
||||
|
||||
public interface ApplicationCallback {
|
||||
Context onAttachBaseContext(Context context);
|
||||
}
|
||||
|
||||
public ApplicationCallback getCallback() {
|
||||
return callback;
|
||||
}
|
||||
|
||||
public void setCallback(ApplicationCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
private ApplicationCallback callback;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
//异常处理
|
||||
CrashUtil.register(this);
|
||||
//全局context,app环境缓存!
|
||||
AppUtil.register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(callback != null ? callback.onAttachBaseContext(base) : base);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.dxl.common.implement;
|
||||
|
||||
import android.view.animation.Animation;
|
||||
|
||||
public class AnimationListenerImpl implements Animation.AnimationListener {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.dxl.common.implement;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
|
||||
public class DialogOnclickListenerImpl implements DialogInterface.OnClickListener {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.dxl.common.implement;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
public class ItemSelectedListenerImpl
|
||||
implements AdapterView.OnItemSelectedListener {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.dxl.common.implement;
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
public class OnPageChangeListenerImpl implements ViewPager.OnPageChangeListener {
|
||||
@Override
|
||||
public void onPageScrolled(int i, float v, int i1) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int i) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int i) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.dxl.common.implement;
|
||||
|
||||
import cn.dxl.common.util.PermissionUtil;
|
||||
|
||||
public class PermissionCallback implements PermissionUtil.Callback {
|
||||
@Override
|
||||
public void onStartChecks(PermissionUtil util) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionLose(PermissionUtil util) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionNormal(PermissionUtil util) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whatPermissionLose(String per, PermissionUtil util) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndChecks() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.dxl.common.interfaces;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/*
|
||||
* 在触发时的回调!
|
||||
* */
|
||||
public interface OnTouchListener {
|
||||
boolean onTouch(MotionEvent event);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.dxl.common.interfaces;
|
||||
|
||||
public interface RegexCommon {
|
||||
|
||||
//邮箱匹配规则!
|
||||
String email = "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?";
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package cn.dxl.common.posixio;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/*
|
||||
* author DXL
|
||||
* 通信接口,实现了必要的元素传递以及通信实现规定
|
||||
*/
|
||||
public interface Communication extends Serializable, Closeable {
|
||||
|
||||
/**
|
||||
* @param sendMsg data buffer, transfer data from here.
|
||||
* @param offset the data from buffer valid offset.
|
||||
* @param length the data length from buffer,buffer may be 1024bytes, but valid data length is 512bytes.
|
||||
* @param timeout if write need timeout, use me.
|
||||
* @return the length of write finished.
|
||||
* @throws IOException throw a IOException if have some problem.
|
||||
*/
|
||||
int write(byte[] sendMsg, int offset, int length, int timeout) throws IOException;
|
||||
|
||||
/**
|
||||
* @param recvMsg data buffer, read data to here.
|
||||
* @param offset read data to buffer from offset started.
|
||||
* @param length the length of data need read.
|
||||
* @param timeout if read need timeout at data length no enough, use me.
|
||||
* @return the length of read finished.
|
||||
* @throws IOException throw a IOException if have some problem.
|
||||
*/
|
||||
int read(byte[] recvMsg, int offset, int length, int timeout) throws IOException;
|
||||
|
||||
/**
|
||||
* flush outputstream.
|
||||
*
|
||||
* @throws IOException throw a IOException if have some problem.
|
||||
*/
|
||||
void flush() throws IOException;
|
||||
|
||||
/**
|
||||
* close io stream
|
||||
*
|
||||
* @throws IOException throw a IOException if have some problem.
|
||||
*/
|
||||
void close() throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package cn.dxl.common.services;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class RestartService extends Service {
|
||||
|
||||
private static final String LOG_TAG = RestartService.class.getSimpleName();
|
||||
private Handler handler;
|
||||
private String PackageName;
|
||||
|
||||
public RestartService() {
|
||||
handler = new Handler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
/*
|
||||
* 关闭应用后多久重新启动
|
||||
*/
|
||||
long stopDelayed = intent.getLongExtra("Delayed", 2000);
|
||||
PackageName = intent.getStringExtra("PackageName");
|
||||
handler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Intent LaunchIntent = RestartService.this.getPackageManager().getLaunchIntentForPackage(PackageName);
|
||||
RestartService.this.startActivity(LaunchIntent);
|
||||
RestartService.this.stopSelf();
|
||||
}
|
||||
}, stopDelayed);
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package cn.dxl.common.util;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* AES 加密方法,是对称的密码算法(加密与解密的密钥一致),这里使用最大的 256 位的密钥
|
||||
*/
|
||||
public class AesUtils {
|
||||
|
||||
private static final int size = 128;
|
||||
|
||||
/**
|
||||
* 获得一个 密钥长度为 256 位的 AES 密钥,
|
||||
*
|
||||
* @return 返回经 BASE64 处理之后的密钥字符串
|
||||
*/
|
||||
public static byte[] getStrKeyAES() throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
|
||||
SecureRandom secureRandom = new SecureRandom(String.valueOf(System.currentTimeMillis()).getBytes(Charset.forName("UTF-8")));
|
||||
keyGen.init(size, secureRandom); // 这里可以是 128、192、256、越大越安全
|
||||
SecretKey secretKey = keyGen.generateKey();
|
||||
return secretKey.getEncoded();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将使用 原生的类型byte的数组 secretKey 转为 SecretKey
|
||||
*
|
||||
* @param keyBytes raw key byte.
|
||||
* @return SecretKey
|
||||
*/
|
||||
public static SecretKey strKey2SecretKey(byte[] keyBytes) {
|
||||
return new SecretKeySpec(keyBytes, "AES");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将使用 byte 类型的 secretKey 转为 SecretKey
|
||||
*
|
||||
* @param bytesKey
|
||||
* @return SecretKey
|
||||
*/
|
||||
public static SecretKey bytesKey2SecretKey(byte[] bytesKey) {
|
||||
return new SecretKeySpec(bytesKey, "AES");
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*
|
||||
* @param content 待加密内容
|
||||
* @param secretKey 加密使用的 AES 密钥
|
||||
* @return 加密后的密文 byte[]
|
||||
*/
|
||||
public static byte[] encryptAES(byte[] content, SecretKey secretKey)
|
||||
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
return cipher.doFinal(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*
|
||||
* @param content 待解密内容
|
||||
* @param secretKey 解密使用的 AES 密钥
|
||||
* @return 解密后的明文 byte[]
|
||||
*/
|
||||
public static byte[] decryptAES(byte[] content, SecretKey secretKey)
|
||||
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||||
return cipher.doFinal(content);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.dxl.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
|
||||
import cn.dxl.common.application.App;
|
||||
|
||||
public class AppUtil {
|
||||
private static AppUtil thiz = null;
|
||||
private static App app;
|
||||
|
||||
private AppUtil() {
|
||||
}
|
||||
|
||||
public static AppUtil getInstance() {
|
||||
if (thiz == null) {
|
||||
thiz = new AppUtil();
|
||||
}
|
||||
return thiz;
|
||||
}
|
||||
|
||||
public static void register(App app) {
|
||||
AppUtil.app = app;
|
||||
}
|
||||
|
||||
public App getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void finishAll() {
|
||||
for (Activity activity : CrashUtil.activities) {
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package cn.dxl.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/*
|
||||
* 针对Assets进行操作的类!
|
||||
* */
|
||||
public class AssetsUtil {
|
||||
|
||||
private Context context;
|
||||
|
||||
public AssetsUtil(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
//判断assets文件是否存在!
|
||||
public boolean isFileExists(String fileName) {
|
||||
InputStream is = null;
|
||||
boolean ret = false;
|
||||
try {
|
||||
is = context.getResources().getAssets().open(fileName);
|
||||
ret = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (is != null)
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//得到assets指定目录下的所有文件!
|
||||
public String[] getFiles(String root) {
|
||||
String[] files = new String[0];
|
||||
try {
|
||||
files = context.getAssets().list(root);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (files == null || files.length == 0) return null;
|
||||
return files;
|
||||
}
|
||||
|
||||
//移动assets中的文件到指定目录
|
||||
public boolean moveFile(String asFile, String targetPath) {
|
||||
File file = new File(targetPath);
|
||||
if (!file.exists() || !file.isFile()) {
|
||||
try {
|
||||
if (!file.createNewFile()) {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
boolean ret = false;
|
||||
//移动默认key文件
|
||||
AssetManager am = context.getResources().getAssets();
|
||||
InputStream is = null;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
is = am.open(asFile);
|
||||
fos = new FileOutputStream(file);
|
||||
int len = is.available();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
fos.write((byte) is.read());
|
||||
}
|
||||
ret = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
if (is != null) is.close();
|
||||
if (fos != null) fos.close();
|
||||
ret = false;
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) is.close();
|
||||
if (fos != null) fos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package cn.dxl.common.util;
|
||||
|
||||
/**
|
||||
* crc16多项式算法
|
||||
*
|
||||
* @author eguid
|
||||
*/
|
||||
public class CRC16 {
|
||||
|
||||
/**
|
||||
* CRC16-XMODEM算法(四字节)
|
||||
*
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public static int crc16_ccitt_xmodem(byte[] bytes) {
|
||||
return crc16_ccitt_xmodem(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* CRC16-XMODEM算法(四字节)
|
||||
*
|
||||
* @param bytes
|
||||
* @param offset
|
||||
* @param count
|
||||
* @return
|
||||
*/
|
||||
public static int crc16_ccitt_xmodem(byte[] bytes, int offset, int count) {
|
||||
int crc = 0x0000; // initial value
|
||||
int polynomial = 0x1021; // poly value
|
||||
for (int index = offset; index < count; index++) {
|
||||
byte b = bytes[index];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
boolean bit = ((b >> (7 - i) & 1) == 1);
|
||||
boolean c15 = ((crc >> 15 & 1) == 1);
|
||||
crc <<= 1;
|
||||
if (c15 ^ bit)
|
||||
crc ^= polynomial;
|
||||
}
|
||||
}
|
||||
crc &= 0xffff;
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* CRC16-XMODEM算法(两字节)
|
||||
*
|
||||
* @param bytes
|
||||
* @param offset
|
||||
* @param count
|
||||
* @return
|
||||
*/
|
||||
public static short crc16_ccitt_xmodem_short(byte[] bytes, int offset, int count) {
|
||||
return (short) crc16_ccitt_xmodem(bytes, offset, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* CRC16-XMODEM算法(两字节)
|
||||
*
|
||||
* @param bytes
|
||||
*/
|
||||
public static short crc16_ccitt_xmodem_short(byte[] bytes) {
|
||||
return crc16_ccitt_xmodem_short(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.dxl.common.util;
|
||||
|
||||
public class Checksum {
|
||||
/**
|
||||
* Calculates the checksum of the passed byte buffer.
|
||||
*
|
||||
* @param buffer
|
||||
* @param byteCount
|
||||
* @return byte checksum value
|
||||
*/
|
||||
public static byte calcChecksum(byte[] buffer, int byteCount) {
|
||||
byte checksum = 0;
|
||||
int bufPos = 0;
|
||||
while (byteCount-- != 0) {
|
||||
checksum += buffer[bufPos++];
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.dxl.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
|
||||
public class ContextUtil {
|
||||
|
||||
private Context context;
|
||||
|
||||
public ContextUtil(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
//根据colorId得到颜色
|
||||
public int getColor(int colorId) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
return context.getColor(colorId);
|
||||
}
|
||||
return context.getResources().getColor(colorId);
|
||||
}
|
||||
|
||||
//根据drawableId得到drawable对象
|
||||
public Drawable getDrawable(int drawableId) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
return context.getDrawable(drawableId);
|
||||
}
|
||||
return context.getResources().getDrawable(drawableId);
|
||||
}
|
||||
|
||||
//复制文本到剪贴板
|
||||
public void copyStr2Clipborad(String label, String content) {
|
||||
ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (clipboardManager == null) return;
|
||||
//创建ClipData对象
|
||||
ClipData clipData = ClipData.newPlainText(label, content);
|
||||
//添加ClipData对象到剪切板中
|
||||
clipboardManager.setPrimaryClip(clipData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package cn.dxl.common.util;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/*
|
||||
* 倒计时任务!
|
||||
* */
|
||||
public class CountDownTask extends TimerTask {
|
||||
|
||||
private int timeDelay = 1000;
|
||||
private transient int countdynamic = 0;
|
||||
private Progress mProgress;
|
||||
private Timer timer;
|
||||
|
||||
public CountDownTask(Progress progress) {
|
||||
timer = new Timer();
|
||||
mProgress = progress;
|
||||
}
|
||||
|
||||
//倒计时回调接口
|
||||
public interface Progress {
|
||||
boolean onProgress(int countdynamic);
|
||||
}
|
||||
|
||||
//设置回调!
|
||||
public void setProgress(Progress progress) {
|
||||
mProgress = progress;
|
||||
}
|
||||
|
||||
//设置每次的延迟
|
||||
public CountDownTask setTimeDelay(int ms) {
|
||||
timeDelay = ms;
|
||||
return this;
|
||||
}
|
||||
|
||||
//设置需要延迟多少次!
|
||||
public CountDownTask setCountDown(int count) {
|
||||
countdynamic = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
//开始倒计时!
|
||||
public CountDownTask startCountDown() {
|
||||
if (countdynamic == 0) return this;
|
||||
timer.schedule(this, 0, timeDelay);
|
||||
return this;
|
||||
}
|
||||
|
||||
//取消倒计时
|
||||
public CountDownTask cancelCountDown() {
|
||||
cancel();
|
||||
countdynamic = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
//是否处于倒计时状态!
|
||||
public boolean isRunning() {
|
||||
return this.countdynamic != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//判断为零,立刻回调结束
|
||||
if (countdynamic == 0) {
|
||||
mProgress.onProgress(0);
|
||||
cancelCountDown();
|
||||
} else {
|
||||
//回调且判断需不需要继续下次回调!
|
||||
if (!mProgress.onProgress(countdynamic)) {
|
||||
cancelCountDown();
|
||||
return;
|
||||
}
|
||||
--countdynamic;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package cn.dxl.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cn.dxl.common.activities.CrashActivity;
|
||||
|
||||
public class CrashUtil {
|
||||
private static final Thread.UncaughtExceptionHandler DEFAULT_UNCAUGHT = Thread.getDefaultUncaughtExceptionHandler();
|
||||
public static final List<Activity> activities = new ArrayList<>();
|
||||
|
||||
/*
|
||||
* callback for activity!
|
||||
* */
|
||||
private static final
|
||||
Application.ActivityLifecycleCallbacks callbacks4Act = new Application.ActivityLifecycleCallbacks() {
|
||||
@Override
|
||||
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle bundle) {
|
||||
//must add activity to list!
|
||||
activities.add(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(@NonNull Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(@NonNull Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(@NonNull Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(@NonNull Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle bundle) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(@NonNull Activity activity) {
|
||||
//must remove activity from list!
|
||||
activities.remove(activity);
|
||||
}
|
||||
};
|
||||
|
||||
public static void register(final Application application) {
|
||||
//register callback!
|
||||
application.registerActivityLifecycleCallbacks(callbacks4Act);
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
@Override
|
||||
public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
|
||||
//跳转到奔溃信息处理界面
|
||||
Intent intent = new Intent(application, CrashActivity.class);
|
||||
intent.putExtra("crash", e);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
//destroy all activity
|
||||
for (Activity act : activities) {
|
||||
act.finish();
|
||||
}
|
||||
application.startActivity(intent);
|
||||
//调用默认的异常处理
|
||||
if (DEFAULT_UNCAUGHT != null) {
|
||||
DEFAULT_UNCAUGHT.uncaughtException(t, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user