diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f97a69f..e5fe698 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -71,7 +71,7 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + diff --git a/app/src/main/java/com/uiuipad/find/activity/MainActivity.java b/app/src/main/java/com/uiuipad/find/activity/MainActivity.java deleted file mode 100644 index 822270a..0000000 --- a/app/src/main/java/com/uiuipad/find/activity/MainActivity.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.uiuipad.find.activity; - -import androidx.appcompat.app.AppCompatActivity; - -import android.os.Bundle; - -import com.uiuipad.find.R; - -public class MainActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - } - - -} diff --git a/app/src/main/java/com/uiuipad/find/activity/main/MainAContact.java b/app/src/main/java/com/uiuipad/find/activity/main/MainAContact.java new file mode 100644 index 0000000..81b598c --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/activity/main/MainAContact.java @@ -0,0 +1,17 @@ +package com.uiuipad.find.activity.main; + +import android.graphics.Bitmap; + +import com.uiuipad.find.base.BasePresenter; +import com.uiuipad.find.base.BaseView; + +public class MainAContact { + interface Presenter extends BasePresenter { + /*获取二维码*/ + void getQrCode(); + } + + public interface MainView extends BaseView { + void setQrCode(Bitmap bitmap); + } +} diff --git a/app/src/main/java/com/uiuipad/find/activity/main/MainAPresenter.java b/app/src/main/java/com/uiuipad/find/activity/main/MainAPresenter.java new file mode 100644 index 0000000..e34742c --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/activity/main/MainAPresenter.java @@ -0,0 +1,56 @@ +package com.uiuipad.find.activity.main; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.Log; + +import com.trello.rxlifecycle4.android.ActivityEvent; +import com.uiuipad.find.comm.CommonConfig; +import com.uiuipad.find.util.BitmapUtils; +import com.uiuipad.find.util.CXAESUtil; +import com.uiuipad.find.util.Utils; + +import io.reactivex.rxjava3.subjects.BehaviorSubject; + +/** + * @author jgy02 + */ +public class MainAPresenter implements MainAContact.Presenter { + private static final String TAG = MainAPresenter.class.getSimpleName(); + + private MainAContact.MainView mView; + private Context mContext; + + public MainAPresenter(Context context) { + this.mContext = context; + } + + private BehaviorSubject lifecycle; + + public void setLifecycle(BehaviorSubject lifecycle) { + this.lifecycle = lifecycle; + } + + public BehaviorSubject getLifecycle() { + return lifecycle; + } + + @Override + public void attachView(MainAContact.MainView view) { + this.mView = view; + } + + @Override + public void detachView() { + this.mView = null; + } + + @Override + public void getQrCode() { + String encryptString = CXAESUtil.encrypt(CommonConfig.AES_KEY, Utils.getSerial()); + Log.e("getQRCode", "setImageAndText: " + encryptString); + Bitmap bitmap = BitmapUtils.createQRImage(encryptString, 400, 400); + mView.setQrCode(bitmap); + } + +} diff --git a/app/src/main/java/com/uiuipad/find/activity/main/MainActivity.java b/app/src/main/java/com/uiuipad/find/activity/main/MainActivity.java new file mode 100644 index 0000000..1911acc --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/activity/main/MainActivity.java @@ -0,0 +1,53 @@ +package com.uiuipad.find.activity.main; + +import android.graphics.Bitmap; + +import com.blankj.utilcode.util.NetworkUtils; +import com.uiuipad.find.R; +import com.uiuipad.find.base.BaseActivity; + +import butterknife.ButterKnife; + +public class MainActivity extends BaseActivity implements MainAContact.MainView, NetworkUtils.OnNetworkStatusChangedListener{ + private static final String TAG = MainActivity.class.getSimpleName(); + + private MainAPresenter mPresenter; + + + @Override + public void onDisconnected() { + + } + + @Override + public void onConnected(NetworkUtils.NetworkType networkType) { + + } + + @Override + public int getLayoutId() { + return R.layout.activity_main; + } + + @Override + public void initView() { + ButterKnife.bind(this); + mPresenter = new MainAPresenter(this); + mPresenter.setLifecycle(lifecycleSubject); + mPresenter.attachView(this); + NetworkUtils.registerNetworkStatusChangedListener(this); + } + + @Override + public void initData() { + + } + + + + + @Override + public void setQrCode(Bitmap bitmap) { + + } +} diff --git a/app/src/main/java/com/uiuipad/find/base/BaseActivity.java b/app/src/main/java/com/uiuipad/find/base/BaseActivity.java index 6ad1783..5579348 100644 --- a/app/src/main/java/com/uiuipad/find/base/BaseActivity.java +++ b/app/src/main/java/com/uiuipad/find/base/BaseActivity.java @@ -64,12 +64,12 @@ public abstract class BaseActivity extends AppCompatActivity implements Lifecycl UltimateBarX.statusBar(this) .transparent() .colorRes(R.color.colorPrimaryDark) -// .light(true) + .light(true) .apply(); UltimateBarX.navigationBar(this) .transparent() .colorRes(R.color.colorPrimaryDark) -// .light(true) + .light(true) .apply(); setContentView(this.getLayoutId()); initView(); diff --git a/app/src/main/java/com/uiuipad/find/comm/CommonConfig.java b/app/src/main/java/com/uiuipad/find/comm/CommonConfig.java index acb9f77..0c1ef36 100644 --- a/app/src/main/java/com/uiuipad/find/comm/CommonConfig.java +++ b/app/src/main/java/com/uiuipad/find/comm/CommonConfig.java @@ -3,6 +3,8 @@ package com.uiuipad.find.comm; public class CommonConfig { public static final String MMKV_ID = "InterProcessKV"; + public static final String AES_KEY = "0123456789ABCDEF"; + public static final String MAP_LOCATION_JSON_KEY = "MAPLOCATION_JSON_STRING"; public static final String MAP_LONGITUDE_KEY = "map_longitude_key"; public static final String MAP_LATITUDE_KEY = "map_latitude_key"; diff --git a/app/src/main/java/com/uiuipad/find/util/BitmapUtils.java b/app/src/main/java/com/uiuipad/find/util/BitmapUtils.java new file mode 100644 index 0000000..feac0cc --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/util/BitmapUtils.java @@ -0,0 +1,68 @@ +package com.uiuipad.find.util; + +import android.graphics.Bitmap; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; + +import java.util.HashMap; +import java.util.Map; + +public class BitmapUtils { + public static Bitmap createQRImage(String content, int widthPix, int heightPix) { + try { +// if (content == null || "".equals(content)) { +// return false; +// } + + //配置参数 + Map hints = new HashMap<>(); + hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); + //容错级别 + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); + //设置空白边距的宽度 + hints.put(EncodeHintType.MARGIN, 1); //default is 4 + + // 图像数据转换,使用了矩阵转换 + BitMatrix bitMatrix = null; + try { + bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix, + heightPix, hints); + } catch (WriterException e) { + e.printStackTrace(); + } + int[] pixels = new int[widthPix * heightPix]; + // 下面这里按照二维码的算法,逐个生成二维码的图片, + // 两个for循环是图片横列扫描的结果 + for (int y = 0; y < heightPix; y++) { + for (int x = 0; x < widthPix; x++) { + if (bitMatrix.get(x, y)) { + pixels[y * widthPix + x] = 0xff0480ff; + } else { + pixels[y * widthPix + x] = 0xffffffff; + } + } + } + + // 生成二维码图片的格式,使用ARGB_8888 + Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix); +// +// if (logoBm != null) { +// bitmap = addLogo(bitmap, logoBm); +// } + + //必须使用compress方法将bitmap保存到文件中再进行读取。直接返回的bitmap是没有任何压缩的, + // 内存消耗巨大! + return bitmap; +// return bitmap != null && bitmap.compress(Bitmap.CompressFormat.JPEG, 100); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/uiuipad/find/util/CXAESUtil.java b/app/src/main/java/com/uiuipad/find/util/CXAESUtil.java new file mode 100644 index 0000000..a2a94b6 --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/util/CXAESUtil.java @@ -0,0 +1,331 @@ +package com.uiuipad.find.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public class CXAESUtil { + /** + * 加解密算法/工作模式/填充方式 + */ + private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; + public final static String HEX = "0123456789ABCDEF"; + private static final int keyLenght = 16; + private static final String defaultV = "0"; + + /** + * 加密 + * + * @param key 密钥 + * @param src 加密文本 + * @return + * @throws Exception + */ + public static String encrypt(String key, String src) { + // /src = Base64.encodeToString(src.getBytes(), Base64.DEFAULT); + byte[] rawKey = toMakekey(key, keyLenght, defaultV).getBytes();// key.getBytes(); + try { + byte[] result = encrypt(rawKey, src.getBytes("utf-8")); + // result = Base64.encode(result, Base64.DEFAULT); + return toHex(result); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + /** + * 加密 + * + * @param key 密钥 + * @param src 加密文本 + * @return + * @throws Exception + */ + public static String encrypt2Java(String key, String src) throws Exception { + // /src = Base64.encodeToString(src.getBytes(), Base64.DEFAULT); + byte[] rawKey = toMakekey(key, keyLenght, defaultV).getBytes();// key.getBytes(); + byte[] result = encrypt2Java(rawKey, src.getBytes("utf-8")); + // result = Base64.encode(result, Base64.DEFAULT); + return toHex(result); + } + + /** + * 解密 + * + * @param key 密钥 + * @param encrypted 待揭秘文本 + * @return + * @throws Exception + */ + public static String decrypt(String key, String encrypted) throws Exception { + byte[] rawKey = toMakekey(key, keyLenght, defaultV).getBytes();// key.getBytes(); + byte[] enc = toByte(encrypted); + // enc = Base64.decode(enc, Base64.DEFAULT); + byte[] result = decrypt(rawKey, enc); + // /result = Base64.decode(result, Base64.DEFAULT); + return new String(result, "utf-8"); + } + + /** + * 密钥key ,默认补的数字,补全16位数,以保证安全补全至少16位长度,android和ios对接通过 + * + * @param str + * @param strLength + * @param val + * @return + */ + private static String toMakekey(String str, int strLength, String val) { + + int strLen = str.length(); + if (strLen < strLength) { + while (strLen < strLength) { + StringBuffer buffer = new StringBuffer(); + buffer.append(str).append(val); + str = buffer.toString(); + strLen = str.length(); + } + } + return str; + } + + /** + * 真正的加密过程 + * 1.通过密钥得到一个密钥专用的对象SecretKeySpec + * 2.Cipher 加密算法,加密模式和填充方式三部分或指定加密算 (可以只用写算法然后用默认的其他方式)Cipher.getInstance("AES"); + * + * @param key + * @param src + * @return + * @throws Exception + */ + private static byte[] encrypt(byte[] key, byte[] src) throws Exception { + SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); + byte[] encrypted = cipher.doFinal(src); + return encrypted; + } + + /** + * 真正的加密过程 + * + * @param key + * @param src + * @return + * @throws Exception + */ + private static byte[] encrypt2Java(byte[] key, byte[] src) throws Exception { + SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); + byte[] encrypted = cipher.doFinal(src); + return encrypted; + } + + /** + * 真正的解密过程 + * + * @param key + * @param encrypted + * @return + * @throws Exception + */ + private static byte[] decrypt(byte[] key, byte[] encrypted) throws Exception { + SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); + byte[] decrypted = cipher.doFinal(encrypted); + return decrypted; + } + + public static String toHex(String txt) { + return toHex(txt.getBytes()); + } + + public static String fromHex(String hex) { + return new String(toByte(hex)); + } + + + /** + * 把16进制转化为字节数组 + * + * @param hexString + * @return + */ + public static byte[] toByte(String hexString) { + int len = hexString.length() / 2; + byte[] result = new byte[len]; + for (int i = 0; i < len; i++) + result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); + return result; + } + + + /** + * 二进制转字符,转成了16进制 + * 0123456789abcdefg + * + * @param buf + * @return + */ + public static String toHex(byte[] buf) { + if (buf == null) + return ""; + StringBuffer result = new StringBuffer(2 * buf.length); + for (int i = 0; i < buf.length; i++) { + appendHex(result, buf[i]); + } + return result.toString(); + } + + private static void appendHex(StringBuffer sb, byte b) { + sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); + } + + /** + * 初始化 AES Cipher + * + * @param sKey + * @param cipherMode + * @return + */ + public static Cipher initAESCipher(String sKey, int cipherMode) { + // 创建Key gen + // KeyGenerator keyGenerator = null; + Cipher cipher = null; + try { + /* + * keyGenerator = KeyGenerator.getInstance("AES"); + * keyGenerator.init(128, new SecureRandom(sKey.getBytes())); + * SecretKey secretKey = keyGenerator.generateKey(); byte[] + * codeFormat = secretKey.getEncoded(); SecretKeySpec key = new + * SecretKeySpec(codeFormat, "AES"); cipher = + * Cipher.getInstance("AES"); //初始化 cipher.init(cipherMode, key); + */ + byte[] rawKey = toMakekey(sKey, keyLenght, defaultV).getBytes(); + SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES"); + cipher = Cipher.getInstance("AES"); + cipher.init(cipherMode, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); // To change body of catch statement use File | + // Settings | File Templates. + } catch (NoSuchPaddingException e) { + e.printStackTrace(); // To change body of catch statement use File | + // Settings | File Templates. + } catch (InvalidKeyException e) { + e.printStackTrace(); // To change body of catch statement use File | + // Settings | File Templates. + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + return cipher; + } + + /** + * 对文件进行AES加密 + * + * @param sourceFile + * @param sKey + * @return + */ + public static File encryptFile(File sourceFile, String toFile, String dir, String sKey) { + // 新建临时加密文件 + File encrypfile = null; + InputStream inputStream = null; + OutputStream outputStream = null; + try { + inputStream = new FileInputStream(sourceFile); + encrypfile = new File(dir + toFile); + outputStream = new FileOutputStream(encrypfile); + Cipher cipher = initAESCipher(sKey, Cipher.ENCRYPT_MODE); + // 以加密流写入文件 + CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher); + byte[] cache = new byte[1024]; + int nRead = 0; + while ((nRead = cipherInputStream.read(cache)) != -1) { + outputStream.write(cache, 0, nRead); + outputStream.flush(); + } + cipherInputStream.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); // To change body of catch statement use File | + // Settings | File Templates. + } catch (IOException e) { + e.printStackTrace(); // To change body of catch statement use File | + // Settings | File Templates. + } finally { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); // To change body of catch statement use + // File | Settings | File Templates. + } + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); // To change body of catch statement use + // File | Settings | File Templates. + } + } + return encrypfile; + } + + /** + * AES方式解密文件 + * + * @param sourceFile + * @return + */ + public static File decryptFile(File sourceFile, String toFile, String dir, String sKey) { + File decryptFile = null; + InputStream inputStream = null; + OutputStream outputStream = null; + try { + decryptFile = new File(dir + toFile); + Cipher cipher = initAESCipher(sKey, Cipher.DECRYPT_MODE); + inputStream = new FileInputStream(sourceFile); + outputStream = new FileOutputStream(decryptFile); + CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher); + byte[] buffer = new byte[1024]; + int r; + while ((r = inputStream.read(buffer)) >= 0) { + cipherOutputStream.write(buffer, 0, r); + } + cipherOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); // To change body of catch statement use File | + // Settings | File Templates. + } finally { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); // To change body of catch statement use + // File | Settings | File Templates. + } + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); // To change body of catch statement use + // File | Settings | File Templates. + } + } + return decryptFile; + } + +} diff --git a/app/src/main/java/com/uiuipad/find/util/Utils.java b/app/src/main/java/com/uiuipad/find/util/Utils.java index 449a35f..811bbcb 100644 --- a/app/src/main/java/com/uiuipad/find/util/Utils.java +++ b/app/src/main/java/com/uiuipad/find/util/Utils.java @@ -33,4 +33,6 @@ public class Utils { } return serial; } + + } diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml new file mode 100644 index 0000000..34528b9 --- /dev/null +++ b/app/src/main/res/layout-land/activity_main.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-port/activity_main.xml b/app/src/main/res/layout-port/activity_main.xml new file mode 100644 index 0000000..34528b9 --- /dev/null +++ b/app/src/main/res/layout-port/activity_main.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index de1395d..0000000 --- a/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 030098f..7a4330e 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,6 +1,11 @@ - #6200EE - #3700B3 - #03DAC5 + #efefef + #303F9F + #4880ff + + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 5885930..0eb88fe 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ -