1.修复漏洞:BaseDao 中的 SQL 注入
2.移除ACCESS_MOCK_LOCATION 权限 3.MMKV启用AES-256加密保存
This commit is contained in:
2
.idea/deploymentTargetSelector.xml
generated
2
.idea/deploymentTargetSelector.xml
generated
@@ -4,7 +4,7 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2026-06-25T10:07:54.478573Z">
|
<DropdownSelection timestamp="2026-07-01T08:15:08.155754600Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=3A251FDJH000CE" />
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=3A251FDJH000CE" />
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ android {
|
|||||||
applicationId "com.abbidot.tracker"
|
applicationId "com.abbidot.tracker"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 35
|
targetSdkVersion 35
|
||||||
versionCode 2214
|
versionCode 2215
|
||||||
// versionName "2.2.14"
|
// versionName "2.2.15"
|
||||||
versionName "2.2.14-Beta1"
|
versionName "2.2.15-Beta1"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
|||||||
177
app/proguard-rules.pro
vendored
177
app/proguard-rules.pro
vendored
@@ -23,12 +23,175 @@
|
|||||||
|
|
||||||
|
|
||||||
#禁用所有优化规则,查看混淆后 APK是否可以正常工作
|
#禁用所有优化规则,查看混淆后 APK是否可以正常工作
|
||||||
-dontoptimize
|
#-dontoptimize
|
||||||
|
|
||||||
# Please add these rules to your existing keep rules in order to suppress warnings.
|
# 基础混淆配置
|
||||||
# This is generated automatically by the Android Gradle plugin.
|
-optimizationpasses 5
|
||||||
-dontwarn com.baidu.mapsdkplatform.comapi.util.SysOSAPI
|
-dontusemixedcaseclassnames
|
||||||
-dontwarn com.daimajia.easing.Glider
|
-dontskipnonpubliclibraryclasses
|
||||||
-dontwarn com.daimajia.easing.Skill
|
-dontskipnonpubliclibraryclassmembers
|
||||||
|
-dontpreverify
|
||||||
|
-verbose
|
||||||
|
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||||
|
|
||||||
-keep class android.*
|
# 保留注解、泛型、异常信息
|
||||||
|
-keepattributes *Annotation*,Signature,Exception
|
||||||
|
-keepattributes InnerClasses,EnclosingMethod
|
||||||
|
|
||||||
|
# Android基础组件保护
|
||||||
|
-keep public class * extends android.app.Activity
|
||||||
|
-keep public class * extends android.app.Service
|
||||||
|
-keep public class * extends android.content.BroadcastReceiver
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||||
|
-keep public class * extends android.preference.Preference
|
||||||
|
-keep public class com.android.vending.licensing.ILicensingService
|
||||||
|
|
||||||
|
# 保留Activity生命周期方法
|
||||||
|
-keepclassmembers public class * extends android.app.Activity {
|
||||||
|
public void *(android.view.View);
|
||||||
|
public void on*(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保留Service生命周期方法
|
||||||
|
-keepclassmembers public class * extends android.app.Service {
|
||||||
|
public void on*(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保留BroadcastReceiver接收方法
|
||||||
|
-keepclassmembers class * extends android.content.BroadcastReceiver {
|
||||||
|
public void onReceive(android.content.Context, android.content.Intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保留ContentProvider方法
|
||||||
|
-keepclassmembers class * extends android.content.ContentProvider {
|
||||||
|
public android.net.Uri insert(android.net.Uri, android.content.ContentValues);
|
||||||
|
public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
|
||||||
|
public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
|
||||||
|
public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保留R文件
|
||||||
|
-keep class **.R$* { *; }
|
||||||
|
|
||||||
|
# Parcelable和Serializable支持
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
||||||
|
-keepclassmembers class * implements java.io.Serializable {
|
||||||
|
static final long serialVersionUID;
|
||||||
|
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||||
|
!static !transient <fields>;
|
||||||
|
private void writeObject(java.io.ObjectOutputStream);
|
||||||
|
private void readObject(java.io.ObjectInputStream);
|
||||||
|
java.lang.Object writeReplace();
|
||||||
|
java.lang.Object readResolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
# Kotlin特定规则
|
||||||
|
-keep class kotlin.** { *; }
|
||||||
|
-keep class kotlin.Metadata { *; }
|
||||||
|
-dontwarn kotlin.**
|
||||||
|
-keepclassmembers class **$WhenMappings {
|
||||||
|
<fields>;
|
||||||
|
}
|
||||||
|
-keepclassmembers class kotlinx.coroutines.internal.MainCoroutineDispatcherFactory {
|
||||||
|
public <init>();
|
||||||
|
}
|
||||||
|
-keepclassmembers class kotlinx.coroutines.CoroutineExceptionHandler {
|
||||||
|
public <init>();
|
||||||
|
}
|
||||||
|
|
||||||
|
# 数据类保护(根据项目实际数据类包名调整)
|
||||||
|
-keep class com.abbidot.tracker.data.** { *; }
|
||||||
|
-keep class com.abbidot.tracker.model.** { *; }
|
||||||
|
|
||||||
|
# ViewBinding支持
|
||||||
|
-keep class com.abbidot.tracker.databinding.** { *; }
|
||||||
|
|
||||||
|
# Hilt依赖注入
|
||||||
|
-keep class dagger.hilt.android.lifecycle.HiltViewModelFactory { *; }
|
||||||
|
-keep class * extends dagger.hilt.android.lifecycle.HiltViewModel { *; }
|
||||||
|
-keep @dagger.hilt.android.lifecycle.HiltViewModel class * { *; }
|
||||||
|
-keep @dagger.hilt.android.AndroidEntryPoint class * { *; }
|
||||||
|
-keep @dagger.Module class * { *; }
|
||||||
|
-keep @dagger.hilt.EntryPoint class * { *; }
|
||||||
|
|
||||||
|
# Room数据库
|
||||||
|
-keep class * extends androidx.room.RoomDatabase { *; }
|
||||||
|
-keep @androidx.room.Entity class * { *; }
|
||||||
|
-keep interface * extends androidx.room.Dao { *; }
|
||||||
|
-keepclassmembers class * extends androidx.room.RoomDatabase {
|
||||||
|
<methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 第三方库规则
|
||||||
|
|
||||||
|
# Coil图片加载
|
||||||
|
-keep class io.coil.** { *; }
|
||||||
|
-dontwarn io.coil.**
|
||||||
|
|
||||||
|
# Lottie动画
|
||||||
|
-keep class com.airbnb.lottie.** { *; }
|
||||||
|
-dontwarn com.airbnb.lottie.**
|
||||||
|
|
||||||
|
# BaseRecyclerViewAdapterHelper
|
||||||
|
-keep class com.chad.library.adapter.** { *; }
|
||||||
|
-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter
|
||||||
|
-keep public class * extends com.chad.library.adapter.base.BaseViewHolder
|
||||||
|
|
||||||
|
# Mapbox
|
||||||
|
-keep class com.mapbox.** { *; }
|
||||||
|
-dontwarn com.mapbox.**
|
||||||
|
|
||||||
|
# 百度地图
|
||||||
|
-keep class com.baidu.** { *; }
|
||||||
|
-keep class vi.com.gdi.bgl.android.** { *; }
|
||||||
|
-dontwarn com.baidu.**
|
||||||
|
|
||||||
|
# 极光推送
|
||||||
|
-keep class cn.jiguang.** { *; }
|
||||||
|
-dontwarn cn.jiguang.**
|
||||||
|
|
||||||
|
# Stripe支付
|
||||||
|
-keep class com.stripe.** { *; }
|
||||||
|
-dontwarn com.stripe.**
|
||||||
|
|
||||||
|
# Braintree支付
|
||||||
|
-keep class com.braintreepayments.** { *; }
|
||||||
|
-dontwarn com.braintreepayments.**
|
||||||
|
|
||||||
|
# 微信SDK
|
||||||
|
-keep class com.tencent.mm.opensdk.** { *; }
|
||||||
|
-keep class com.tencent.wxop.** { *; }
|
||||||
|
-keep class com.tencent.mm.sdk.** { *; }
|
||||||
|
|
||||||
|
# 支付宝SDK
|
||||||
|
-keep class com.alipay.** { *; }
|
||||||
|
-dontwarn com.alipay.**
|
||||||
|
|
||||||
|
# DFU升级库
|
||||||
|
-keep class no.nordicsemi.android.** { *; }
|
||||||
|
-dontwarn no.nordicsemi.android.**
|
||||||
|
|
||||||
|
# 测试相关
|
||||||
|
-dontnote junit.framework.**
|
||||||
|
-dontnote junit.runner.**
|
||||||
|
-dontwarn android.test.**
|
||||||
|
-dontwarn android.support.test.**
|
||||||
|
-dontwarn org.junit.**
|
||||||
|
|
||||||
|
# 移除日志(发布版)
|
||||||
|
-assumenosideeffects class android.util.Log {
|
||||||
|
public static boolean isLoggable(java.lang.String, int);
|
||||||
|
public static int v(...);
|
||||||
|
public static int i(...);
|
||||||
|
public static int w(...);
|
||||||
|
public static int d(...);
|
||||||
|
public static int e(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 混淆映射输出
|
||||||
|
-printmapping proguardMapping.txt
|
||||||
|
-printseeds proguardSeeds.txt
|
||||||
|
-printusage proguardUsage.txt
|
||||||
@@ -43,9 +43,9 @@
|
|||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 读取缓存数据 -->
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 读取缓存数据 -->
|
||||||
<!-- 蓝牙扫描权限 -->
|
<!-- 蓝牙扫描权限 -->
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- 获取模拟定位信息 -->
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- 获取模拟定位信息 -->
|
||||||
<uses-permission
|
<!-- <uses-permission-->
|
||||||
android:name="android.permission.ACCESS_MOCK_LOCATION"
|
<!-- android:name="android.permission.ACCESS_MOCK_LOCATION"-->
|
||||||
tools:ignore="MockLocation,ProtectedPermissions" />
|
<!-- tools:ignore="MockLocation,ProtectedPermissions" />-->
|
||||||
|
|
||||||
<permission
|
<permission
|
||||||
android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
|
android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
|
||||||
@@ -95,7 +95,8 @@
|
|||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MyApplication"
|
android:name=".MyApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="false"
|
||||||
|
android:fullBackupContent="false"
|
||||||
android:icon="@mipmap/logo_abbidot"
|
android:icon="@mipmap/logo_abbidot"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
|
|||||||
@@ -578,10 +578,11 @@ abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInfl
|
|||||||
fun <T> dealRequestResult(
|
fun <T> dealRequestResult(
|
||||||
it: Result<T>,
|
it: Result<T>,
|
||||||
getResultCallback: GetResultCallback,
|
getResultCallback: GetResultCallback,
|
||||||
showLoading: Boolean = false,
|
showLoading: Boolean = false,//是否显示loading弹窗
|
||||||
isShowNoDataTip: Boolean = true,
|
isShowNoDataTip: Boolean = true,//是否显示无数据提示
|
||||||
isShowRequestErrorTip: Boolean = true,
|
isShowRequestErrorTip: Boolean = true,//是否显示请求错误提示
|
||||||
isShowCodeError: Boolean = true,
|
isShowCodeError: Boolean = true,//是否显示错误码提示
|
||||||
|
isShowNetCodeMsg: Boolean = false,//是否显示服务器返回message提示
|
||||||
errorTip: String = getString(R.string.txt_net_error)
|
errorTip: String = getString(R.string.txt_net_error)
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
@@ -614,7 +615,9 @@ abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInfl
|
|||||||
|
|
||||||
val data = it.getOrNull()
|
val data = it.getOrNull()
|
||||||
if (null == data) {
|
if (null == data) {
|
||||||
if (isShowRequestErrorTip) {
|
if (isShowNetCodeMsg && exceptionCode == ErrorCode.ERROR.toString()) {
|
||||||
|
showToast(exceptionMessage ?: errorTip)
|
||||||
|
} else if (isShowRequestErrorTip) {
|
||||||
if (NetworkUtil.isNetworkAvailable(mContext)) {
|
if (NetworkUtil.isNetworkAvailable(mContext)) {
|
||||||
showToast(errorTip)
|
showToast(errorTip)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -179,10 +179,11 @@ abstract class BaseFragment<T : ViewBinding>(
|
|||||||
fun <T> dealRequestResult(
|
fun <T> dealRequestResult(
|
||||||
it: Result<T>,
|
it: Result<T>,
|
||||||
getResultCallback: GetResultCallback,
|
getResultCallback: GetResultCallback,
|
||||||
showLoading: Boolean = false,
|
showLoading: Boolean = false,//是否显示loading弹窗
|
||||||
isShowNoDataTip: Boolean = true,
|
isShowNoDataTip: Boolean = true,//是否显示无数据提示
|
||||||
isRequestErrorTip: Boolean = true,
|
isRequestErrorTip: Boolean = true,//是否显示请求错误提示
|
||||||
isShowCodeError: Boolean = true,
|
isShowCodeError: Boolean = true,//是否显示错误码提示
|
||||||
|
isShowNetCodeMsg: Boolean = false,//是否显示服务器返回message提示
|
||||||
errorTip: String = getString(R.string.txt_net_error)
|
errorTip: String = getString(R.string.txt_net_error)
|
||||||
) {
|
) {
|
||||||
(activity as BaseActivity<*>).dealRequestResult(
|
(activity as BaseActivity<*>).dealRequestResult(
|
||||||
@@ -191,8 +192,8 @@ abstract class BaseFragment<T : ViewBinding>(
|
|||||||
showLoading,
|
showLoading,
|
||||||
isShowNoDataTip,
|
isShowNoDataTip,
|
||||||
isRequestErrorTip,
|
isRequestErrorTip,
|
||||||
isShowCodeError,
|
isShowCodeError, isShowNetCodeMsg,
|
||||||
errorTip
|
errorTip,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ abstract class MyDatabase : RoomDatabase() {
|
|||||||
private val db: MyDatabase by lazy {
|
private val db: MyDatabase by lazy {
|
||||||
Room.databaseBuilder(MyApplication.instance, MyDatabase::class.java, "tracker_dp")
|
Room.databaseBuilder(MyApplication.instance, MyDatabase::class.java, "tracker_dp")
|
||||||
// .addMigrations(MIGRATION_1_2)
|
// .addMigrations(MIGRATION_1_2)
|
||||||
.fallbackToDestructiveMigration()//删除旧表格并创建新表格,的方式升级数据库版本
|
.fallbackToDestructiveMigration(true)//删除旧表格并创建新表格,的方式升级数据库版本
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package com.abbidot.tracker.database.dao
|
package com.abbidot.tracker.database.dao
|
||||||
|
|
||||||
import android.util.Log
|
import androidx.room.Delete
|
||||||
import androidx.room.*
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.RawQuery
|
||||||
|
import androidx.room.Update
|
||||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||||
import androidx.sqlite.db.SupportSQLiteQuery
|
import androidx.sqlite.db.SupportSQLiteQuery
|
||||||
|
import com.abbidot.baselibrary.util.LogUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Created by .yzq on 2022/4/1/001.
|
*Created by .yzq on 2022/4/1/001.
|
||||||
@@ -28,43 +32,43 @@ interface BaseDao<T> {
|
|||||||
* OnConflictStrategy.REPLACE新数据替换旧数据
|
* OnConflictStrategy.REPLACE新数据替换旧数据
|
||||||
*/
|
*/
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insert(obj: T): Long
|
fun insert(obj: T): Long
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加数组对象数据
|
* 添加数组对象数据
|
||||||
*/
|
*/
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insert(vararg objs: T): LongArray?
|
fun insert(vararg objs: T): LongArray?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加对象集合
|
* 添加对象集合
|
||||||
*/
|
*/
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insert(personList: List<T>): List<Long>
|
fun insert(personList: List<T>): List<Long>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据对象中的主键删除(主键是自动增长的,无需手动赋值)
|
* 根据对象中的主键删除(主键是自动增长的,无需手动赋值)
|
||||||
*/
|
*/
|
||||||
@Delete
|
@Delete
|
||||||
fun delete(obj: T)
|
fun delete(obj: T)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据对象中的主键更新(主键是自动增长的,无需手动赋值)
|
* 根据对象中的主键更新(主键是自动增长的,无需手动赋值)
|
||||||
*/
|
*/
|
||||||
@Update
|
@Update
|
||||||
fun update(vararg obj: T): Int
|
fun update(vararg obj: T): Int
|
||||||
|
|
||||||
fun deleteAll(tableName:String): Int {
|
fun deleteAll(tableName: String): Int {
|
||||||
val query = SimpleSQLiteQuery("delete from $tableName")
|
val query = SimpleSQLiteQuery("delete from $tableName")
|
||||||
return doDeleteAll(query)
|
return doDeleteAll(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findAll(tableName:String): List<T>? {
|
fun findAll(tableName: String): List<T>? {
|
||||||
val query = SimpleSQLiteQuery("select * from $tableName")
|
val query = SimpleSQLiteQuery("select * from $tableName")
|
||||||
return doFindAll(query)
|
return doFindAll(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun find(id: Long,tableName:String): T? {
|
fun find(id: Long, tableName: String): T? {
|
||||||
val query = SimpleSQLiteQuery("select * from $tableName where id = ?", arrayOf<Any>(id))
|
val query = SimpleSQLiteQuery("select * from $tableName where id = ?", arrayOf<Any>(id))
|
||||||
return doFind(query)
|
return doFind(query)
|
||||||
}
|
}
|
||||||
@@ -73,9 +77,9 @@ interface BaseDao<T> {
|
|||||||
* [params] 列名
|
* [params] 列名
|
||||||
* [value] 列的值
|
* [value] 列的值
|
||||||
*/
|
*/
|
||||||
fun deleteByParams(params: String, value: String,tableName:String): Int {
|
fun deleteByParams(params: String, value: String, tableName: String): Int {
|
||||||
val query = SimpleSQLiteQuery("delete from $tableName where $params='${value}'")
|
val query = SimpleSQLiteQuery("delete from $tableName where $params= ?", arrayOf(value))
|
||||||
Log.d("ez", "deleteByParams: ${"delete from $tableName where $params='${value}'"}")
|
LogUtil.d("ez", "deleteByParams: ${"delete from $tableName where $params = ?"}")
|
||||||
return doDeleteByParams(query)
|
return doDeleteByParams(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,18 +87,26 @@ interface BaseDao<T> {
|
|||||||
* 分页查询,支持传入多个字段,但必须要按照顺序传入
|
* 分页查询,支持传入多个字段,但必须要按照顺序传入
|
||||||
* key = value,key = value 的形式,一一对应(可以使用 stringbuilder 去构造一下,这里就不演示了)
|
* key = value,key = value 的形式,一一对应(可以使用 stringbuilder 去构造一下,这里就不演示了)
|
||||||
*/
|
*/
|
||||||
fun doQueryByLimit(tableName:String,vararg string: String, limit: Int = 10, offset: Int = 0): List<T>? {
|
fun doQueryByLimit(
|
||||||
|
tableName: String, vararg string: String, limit: Int = 10, offset: Int = 0
|
||||||
|
): List<T>? {
|
||||||
val query = SimpleSQLiteQuery(
|
val query = SimpleSQLiteQuery(
|
||||||
"SELECT * FROM $tableName WHERE ${string[0]} = '${string[1]}' limit $limit offset $offset")
|
"SELECT * FROM $tableName WHERE ${string[0]} = ? limit $limit offset $offset",
|
||||||
|
arrayOf(string[1])
|
||||||
|
)
|
||||||
return doQueryByLimit(query)
|
return doQueryByLimit(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 降序分页查询
|
* 降序分页查询
|
||||||
*/
|
*/
|
||||||
fun doQueryByOrder(tableName:String,vararg string: String, limit: Int = 10, offset: Int = 10): List<T>? {
|
fun doQueryByOrder(
|
||||||
|
tableName: String, vararg string: String, limit: Int = 10, offset: Int = 10
|
||||||
|
): List<T>? {
|
||||||
|
// 修复 SQL 注入:1. 去掉 limit 和 offset 的单引号 2. 确保排序字段安全(建议增加白名单验证)
|
||||||
val query = SimpleSQLiteQuery(
|
val query = SimpleSQLiteQuery(
|
||||||
"SELECT * FROM $tableName ORDER BY ${string[0]} desc limit '${limit}' offset '${offset}'")
|
"SELECT * FROM $tableName ORDER BY ${string[0]} desc limit $limit offset $offset"
|
||||||
|
)
|
||||||
return doQueryByOrder(query)
|
return doQueryByOrder(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import com.abbidot.tracker.R
|
|||||||
import com.abbidot.tracker.base.BaseActivity
|
import com.abbidot.tracker.base.BaseActivity
|
||||||
import com.abbidot.tracker.bean.CreditCardBean
|
import com.abbidot.tracker.bean.CreditCardBean
|
||||||
import com.abbidot.tracker.constant.ConstantString
|
import com.abbidot.tracker.constant.ConstantString
|
||||||
import com.abbidot.tracker.database.MyDatabase
|
|
||||||
import com.abbidot.tracker.databinding.ActivityAddCreditCardBinding
|
import com.abbidot.tracker.databinding.ActivityAddCreditCardBinding
|
||||||
import com.abbidot.tracker.util.Util
|
import com.abbidot.tracker.util.Util
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -123,7 +122,7 @@ class AddCreditCardActivity :
|
|||||||
card.firstName = firstName
|
card.firstName = firstName
|
||||||
card.expirationDate = creditCardValidity
|
card.expirationDate = creditCardValidity
|
||||||
card.cvv = cvv
|
card.cvv = cvv
|
||||||
MyDatabase.creditCardDao().insert(card)
|
// MyDatabase.creditCardDao().insert(card)
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.putExtra(ConstantString.Card, card)
|
intent.putExtra(ConstantString.Card, card)
|
||||||
|
|||||||
@@ -20,16 +20,13 @@ import com.abbidot.tracker.R
|
|||||||
import com.abbidot.tracker.base.BaseActivity
|
import com.abbidot.tracker.base.BaseActivity
|
||||||
import com.abbidot.tracker.constant.ConstantInt
|
import com.abbidot.tracker.constant.ConstantInt
|
||||||
import com.abbidot.tracker.constant.GetResultCallback
|
import com.abbidot.tracker.constant.GetResultCallback
|
||||||
import com.abbidot.tracker.database.MyDatabase
|
|
||||||
import com.abbidot.tracker.databinding.ActivityLoginV2Binding
|
import com.abbidot.tracker.databinding.ActivityLoginV2Binding
|
||||||
import com.abbidot.tracker.ui.activity.set.FirstPermissionsActivity
|
import com.abbidot.tracker.ui.activity.set.FirstPermissionsActivity
|
||||||
import com.abbidot.tracker.util.Util
|
import com.abbidot.tracker.util.Util
|
||||||
import com.abbidot.tracker.util.ViewUtil
|
import com.abbidot.tracker.util.ViewUtil
|
||||||
import com.abbidot.tracker.vm.LoginViewModel
|
import com.abbidot.tracker.vm.LoginViewModel
|
||||||
import com.abbidot.tracker.vm.TrackerInfoViewModel
|
import com.abbidot.tracker.vm.TrackerInfoViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class LoginV2Activity : BaseActivity<ActivityLoginV2Binding>(ActivityLoginV2Binding::inflate) {
|
class LoginV2Activity : BaseActivity<ActivityLoginV2Binding>(ActivityLoginV2Binding::inflate) {
|
||||||
|
|
||||||
@@ -136,14 +133,14 @@ class LoginV2Activity : BaseActivity<ActivityLoginV2Binding>(ActivityLoginV2Bind
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.IO) {
|
// withContext(Dispatchers.IO) {
|
||||||
//保存本地数据库
|
// //保存本地数据库
|
||||||
for (device in list) {
|
// for (device in list) {
|
||||||
if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
// if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
||||||
MyDatabase.deviceDao().insert(device)
|
// MyDatabase.deviceDao().insert(device)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
showToast(R.string.txt_login_successful, gravity = Gravity.CENTER)
|
showToast(R.string.txt_login_successful, gravity = Gravity.CENTER)
|
||||||
|
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class MyTrackerV2Activity :
|
|||||||
//保存本地数据库
|
//保存本地数据库
|
||||||
if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
||||||
bindDeviceNumber++
|
bindDeviceNumber++
|
||||||
MyDatabase.deviceDao().insert(device)
|
// MyDatabase.deviceDao().insert(device)
|
||||||
} else if (!TextUtils.isEmpty(device.deviceOutId) && null == device.pet) {
|
} else if (!TextUtils.isEmpty(device.deviceOutId) && null == device.pet) {
|
||||||
//删除本地没绑定的设备
|
//删除本地没绑定的设备
|
||||||
MyDatabase.deviceDao().deleteByParams(
|
MyDatabase.deviceDao().deleteByParams(
|
||||||
|
|||||||
@@ -118,18 +118,18 @@ class FirstPetProfileActivity :
|
|||||||
mTrackerViewModel.getDeviceListLiveData.observe(this) {
|
mTrackerViewModel.getDeviceListLiveData.observe(this) {
|
||||||
dealRequestResult(it, object : GetResultCallback {
|
dealRequestResult(it, object : GetResultCallback {
|
||||||
override fun onResult(any: Any) {
|
override fun onResult(any: Any) {
|
||||||
it.getOrNull()?.let { list ->
|
// it.getOrNull()?.let { list ->
|
||||||
lifecycleScope.launch {
|
// lifecycleScope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
// withContext(Dispatchers.IO) {
|
||||||
for (device in list) {
|
// for (device in list) {
|
||||||
//保存本地数据库
|
// //保存本地数据库
|
||||||
if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
// if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
||||||
MyDatabase.deviceDao().insert(device)
|
// MyDatabase.deviceDao().insert(device)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
showToast(R.string.txt_bind_success, isFinish = true)
|
showToast(R.string.txt_bind_success, isFinish = true)
|
||||||
mViewBinding.root.postDelayed({
|
mViewBinding.root.postDelayed({
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.abbidot.tracker.ui.activity.subscribe
|
package com.abbidot.tracker.ui.activity.subscribe
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.text.InputFilter
|
import android.text.InputFilter
|
||||||
import android.text.InputFilter.LengthFilter
|
import android.text.InputFilter.LengthFilter
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
@@ -143,7 +144,7 @@ class AddCreditCardPaymentActivity :
|
|||||||
override fun onRequestError(exceptionCode: String?) {
|
override fun onRequestError(exceptionCode: String?) {
|
||||||
setButtonEnabled(mViewBinding.btnSaveNewCreditCard, ConstantInt.Type1)
|
setButtonEnabled(mViewBinding.btnSaveNewCreditCard, ConstantInt.Type1)
|
||||||
}
|
}
|
||||||
})
|
}, isShowNetCodeMsg = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +337,7 @@ class AddCreditCardPaymentActivity :
|
|||||||
it.cardName = cardName
|
it.cardName = cardName
|
||||||
it.expirationDate = creditCardValidity
|
it.expirationDate = creditCardValidity
|
||||||
it.cvv = cvv
|
it.cvv = cvv
|
||||||
MyDatabase.creditCardDao().insert(it)
|
// MyDatabase.creditCardDao().insert(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
@@ -410,28 +411,21 @@ class AddCreditCardPaymentActivity :
|
|||||||
|
|
||||||
override fun onSuccess(result: PaymentMethod) {
|
override fun onSuccess(result: PaymentMethod) {
|
||||||
LogUtil.e(result.toString())
|
LogUtil.e(result.toString())
|
||||||
MyDatabase.creditCardDao()
|
|
||||||
.deleteAll(MyDatabase.CREDIT_CARD_TABLE)
|
|
||||||
it.cardNumber = cardNumber
|
|
||||||
it.cardName = cardName
|
|
||||||
it.expirationDate = creditCardValidity
|
|
||||||
it.cvv = cvv
|
|
||||||
MyDatabase.creditCardDao().insert(it)
|
|
||||||
val paymentMethodID = "${result.id}"
|
val paymentMethodID = "${result.id}"
|
||||||
mSubscriptionPayViewModel.savePaymentMethodInfo(
|
mSubscriptionPayViewModel.savePaymentMethodInfo(paymentMethodID)
|
||||||
paymentMethodID
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
MyDatabase.creditCardDao().deleteAll(MyDatabase.CREDIT_CARD_TABLE)
|
// MyDatabase.creditCardDao().deleteAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||||
it.cardNumber = cardNumber
|
it.cardNumber = cardNumber
|
||||||
it.cardName = cardName
|
it.cardName = cardName
|
||||||
it.expirationDate = creditCardValidity
|
it.expirationDate = creditCardValidity
|
||||||
it.cvv = cvv
|
it.cvv = cvv
|
||||||
MyDatabase.creditCardDao().insert(it)
|
// MyDatabase.creditCardDao().insert(it)
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
setResult(ResultCode.ResultCode_1, null)
|
val intent = Intent()
|
||||||
|
intent.putExtra(ConstantString.Card, it)
|
||||||
|
setResult(ResultCode.ResultCode_1, intent)
|
||||||
showToast(R.string.txt_save_successful, isFinish = true)
|
showToast(R.string.txt_save_successful, isFinish = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.text.TextUtils
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.abbidot.baselibrary.constant.ResultCode
|
import com.abbidot.baselibrary.constant.ResultCode
|
||||||
import com.abbidot.baselibrary.list.BaseRecyclerAdapter
|
import com.abbidot.baselibrary.list.BaseRecyclerAdapter
|
||||||
import com.abbidot.baselibrary.util.AppUtils
|
import com.abbidot.baselibrary.util.AppUtils
|
||||||
@@ -17,20 +16,18 @@ import com.abbidot.tracker.base.BaseFragment
|
|||||||
import com.abbidot.tracker.bean.CreditCardBean
|
import com.abbidot.tracker.bean.CreditCardBean
|
||||||
import com.abbidot.tracker.constant.ConstantString
|
import com.abbidot.tracker.constant.ConstantString
|
||||||
import com.abbidot.tracker.constant.GetResultCallback
|
import com.abbidot.tracker.constant.GetResultCallback
|
||||||
import com.abbidot.tracker.database.MyDatabase
|
|
||||||
import com.abbidot.tracker.databinding.FragmentCreditCardPaymentBinding
|
import com.abbidot.tracker.databinding.FragmentCreditCardPaymentBinding
|
||||||
import com.abbidot.tracker.ui.activity.subscribe.AddCreditCardPaymentActivity
|
import com.abbidot.tracker.ui.activity.subscribe.AddCreditCardPaymentActivity
|
||||||
import com.abbidot.tracker.ui.activity.subscribe.PaymentMethodActivity
|
import com.abbidot.tracker.ui.activity.subscribe.PaymentMethodActivity
|
||||||
import com.abbidot.tracker.ui.activity.subscribe.PaymentSuccessActivity
|
import com.abbidot.tracker.ui.activity.subscribe.PaymentSuccessActivity
|
||||||
import com.abbidot.tracker.util.ThirdPartyUtil
|
import com.abbidot.tracker.util.ThirdPartyUtil
|
||||||
|
import com.abbidot.tracker.util.Util
|
||||||
import com.abbidot.tracker.util.ViewUtil
|
import com.abbidot.tracker.util.ViewUtil
|
||||||
import com.abbidot.tracker.vm.SubscriptionPayViewModel
|
import com.abbidot.tracker.vm.SubscriptionPayViewModel
|
||||||
import com.stripe.android.ApiResultCallback
|
import com.stripe.android.ApiResultCallback
|
||||||
import com.stripe.android.Stripe
|
import com.stripe.android.Stripe
|
||||||
import com.stripe.android.model.PaymentMethod
|
import com.stripe.android.model.PaymentMethod
|
||||||
import com.stripe.android.model.PaymentMethodCreateParams
|
import com.stripe.android.model.PaymentMethodCreateParams
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,6 +84,7 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
|||||||
mContext!!, rvCreditCardPaymentList, mCreditCardAdapter, top = AppUtils.dpToPx(10)
|
mContext!!, rvCreditCardPaymentList, mCreditCardAdapter, top = AppUtils.dpToPx(10)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ilCreditCardPaymentNoData.btnSureSubscribePlan1Continue.visibility = View.GONE
|
||||||
setOnClickListenerViews(btnCreditCardPaymentAdd, btnMakePaymentCreditCard)
|
setOnClickListenerViews(btnCreditCardPaymentAdd, btnMakePaymentCreditCard)
|
||||||
}
|
}
|
||||||
// getCardData()
|
// getCardData()
|
||||||
@@ -94,17 +92,28 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
|||||||
|
|
||||||
fun getCardData(stripeMethodInfo: CreditCardBean) {
|
fun getCardData(stripeMethodInfo: CreditCardBean) {
|
||||||
if (TextUtils.isEmpty(stripeMethodInfo.lastFourNumber)) {
|
if (TextUtils.isEmpty(stripeMethodInfo.lastFourNumber)) {
|
||||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
// viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
val list = MyDatabase.creditCardDao().findAll(MyDatabase.CREDIT_CARD_TABLE)
|
// val list = MyDatabase.creditCardDao().findAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||||
list?.let {
|
// list?.let {
|
||||||
mActivity?.runOnUiThread {
|
// mActivity?.runOnUiThread {
|
||||||
val sortedByList =
|
// val sortedByList =
|
||||||
list.sortedByDescending { l -> l.isPrimary }.toMutableList()
|
// list.sortedByDescending { l -> l.isPrimary }.toMutableList()
|
||||||
setCheckAndPrimaryState(sortedByList)
|
// setCheckAndPrimaryState(sortedByList)
|
||||||
mCreditCardAdapter.setData(sortedByList, true)
|
// mCreditCardAdapter.setData(sortedByList, true)
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//没有卡,显示无卡提示 不用去添加卡
|
||||||
|
mViewBinding.apply {
|
||||||
|
if (null == getHostActivity(PaymentMethodActivity::class.java)?.mOrderBean) {
|
||||||
|
ilCreditCardPaymentNoData.root.visibility = View.VISIBLE
|
||||||
|
rvCreditCardPaymentList.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
ilCreditCardPaymentNoData.root.visibility = View.GONE
|
||||||
|
rvCreditCardPaymentList.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
stripeMethodInfo.apply {
|
stripeMethodInfo.apply {
|
||||||
expirationDate = "$expMonth/$expYear"
|
expirationDate = "$expMonth/$expYear"
|
||||||
@@ -127,8 +136,9 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
|||||||
add(stripeMethodInfo)
|
add(stripeMethodInfo)
|
||||||
mCreditCardAdapter.setData(this, true)
|
mCreditCardAdapter.setData(this, true)
|
||||||
}
|
}
|
||||||
|
mViewBinding.ilCreditCardPaymentNoData.root.visibility = View.GONE
|
||||||
|
ViewUtil.instance.viewShow(mViewBinding.rvCreditCardPaymentList)
|
||||||
}
|
}
|
||||||
ViewUtil.instance.viewShow(mViewBinding.rvCreditCardPaymentList)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun goEditCard(cardBean: CreditCardBean) {
|
fun goEditCard(cardBean: CreditCardBean) {
|
||||||
@@ -162,7 +172,7 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
|||||||
override fun onRequestError(exceptionCode: String?) {
|
override fun onRequestError(exceptionCode: String?) {
|
||||||
showNoCancelableLoading(false)
|
showNoCancelableLoading(false)
|
||||||
}
|
}
|
||||||
})
|
}, isShowNetCodeMsg = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
mCreateStripeOrderLiveData.observe(viewLifecycleOwner) {
|
mCreateStripeOrderLiveData.observe(viewLifecycleOwner) {
|
||||||
@@ -245,7 +255,19 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
|||||||
// }
|
// }
|
||||||
if (it.resultCode == ResultCode.ResultCode_1) {
|
if (it.resultCode == ResultCode.ResultCode_1) {
|
||||||
// getCardData()
|
// getCardData()
|
||||||
getHostActivity(PaymentMethodActivity::class.java)?.getUserPaymentMethodID()
|
if (null != it.data) {
|
||||||
|
val card = Util.getParcelableAdaptive(
|
||||||
|
it.data!!, ConstantString.Card, CreditCardBean::class.java
|
||||||
|
)
|
||||||
|
if (null != card) {
|
||||||
|
val list = mutableListOf<CreditCardBean>()
|
||||||
|
list.add(card)
|
||||||
|
setCheckAndPrimaryState(list)
|
||||||
|
mCreditCardAdapter.setData(list, true)
|
||||||
|
} else getHostActivity(PaymentMethodActivity::class.java)?.getUserPaymentMethodID()
|
||||||
|
} else {
|
||||||
|
getHostActivity(PaymentMethodActivity::class.java)?.getUserPaymentMethodID()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,10 @@ import com.easysocket.interfaces.conn.ISocketActionListener
|
|||||||
*/
|
*/
|
||||||
class SocketUtilManage {
|
class SocketUtilManage {
|
||||||
|
|
||||||
private val iP = "3.101.8.36"
|
private val iP = ""
|
||||||
// private val iP = "192.168.0.69"
|
|
||||||
|
|
||||||
//默认国外服务器端口
|
//默认国外服务器端口
|
||||||
private var port = 8868
|
private var port = 0
|
||||||
|
|
||||||
@OptIn(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
private val crcTable = ushortArrayOf(
|
private val crcTable = ushortArrayOf(
|
||||||
@@ -51,7 +50,7 @@ class SocketUtilManage {
|
|||||||
fun initEasySocket(context: Context) {
|
fun initEasySocket(context: Context) {
|
||||||
if (AppUtils.isChina()) {
|
if (AppUtils.isChina()) {
|
||||||
//国内socket端口号
|
//国内socket端口号
|
||||||
port = 9168
|
port = 1
|
||||||
}
|
}
|
||||||
//socket配置
|
//socket配置
|
||||||
val options = EasySocketOptions.Builder().setSocketAddress(SocketAddress(iP, port))
|
val options = EasySocketOptions.Builder().setSocketAddress(SocketAddress(iP, port))
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import com.abbidot.baselibrary.constant.MMKVKey
|
import com.abbidot.baselibrary.constant.MMKVKey
|
||||||
import com.abbidot.baselibrary.util.LogUtil
|
import com.abbidot.baselibrary.util.LogUtil
|
||||||
import com.abbidot.baselibrary.util.MMKVUtil
|
import com.abbidot.baselibrary.util.MMKVUtil
|
||||||
|
import com.abbidot.baselibrary.util.Utils
|
||||||
import com.abbidot.baselibrary.util.rsa.RSA
|
import com.abbidot.baselibrary.util.rsa.RSA
|
||||||
import com.abbidot.tracker.bean.CreditCardBean
|
import com.abbidot.tracker.bean.CreditCardBean
|
||||||
import com.abbidot.tracker.bean.PayResultBean
|
import com.abbidot.tracker.bean.PayResultBean
|
||||||
@@ -33,7 +34,7 @@ class SubscriptionPayViewModel : ViewModel() {
|
|||||||
/**
|
/**
|
||||||
* Stripe支付创建消费用户
|
* Stripe支付创建消费用户
|
||||||
*/
|
*/
|
||||||
fun createCustomer(card: CreditCardBean,paymentMethodID: String) {
|
fun createCustomer(card: CreditCardBean, paymentMethodID: String) {
|
||||||
// activity.showLoading(true)
|
// activity.showLoading(true)
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val userId = MMKVUtil.getString(MMKVKey.UserId)
|
val userId = MMKVUtil.getString(MMKVKey.UserId)
|
||||||
@@ -48,12 +49,10 @@ class SubscriptionPayViewModel : ViewModel() {
|
|||||||
cardParamsMap["cardName"] = card.cardName
|
cardParamsMap["cardName"] = card.cardName
|
||||||
cardParamsMap["cardnum"] = card.cardNumber
|
cardParamsMap["cardnum"] = card.cardNumber
|
||||||
val cardJso = Gson().toJson(cardParamsMap)
|
val cardJso = Gson().toJson(cardParamsMap)
|
||||||
val b =
|
|
||||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAofuJbnkwyF7SWg3eRadSYT+ttfHN+CUmCzH0WW1EWTUQOG+01Nv8ux+UJUlxbZA2X7959Et/+VKE03+4OY0/26dlgkROMlXCUnzsucuaoHW+9whGi6xklRZrDLi22QBae/8XV1YDEU2vfYXtcvwf66J0t+bRIhGytQUZvUrL7OEaAHvwJU0QwCy3wQGWcCgSkPpDruIe4ar19iZMleE+BdPGIfKfVdPvWFls63g1eMFECb8F9zN6ydGTCvlqvx/4gfDuFQnF+JuTSre8euSpTRTQn/Q0s3K6KiROVcAYCqDW6cKxNUr2ha1C9ZFxMws9C0qhx5wYzfSlIjFthPC1qwIDAQAB"
|
|
||||||
|
|
||||||
val rsaKey = RSA.encrypt(cardJso, b)
|
val rsaKey = RSA.encrypt(cardJso, Utils.CARD_RSA_KEY)
|
||||||
LogUtil.e(cardJso)
|
LogUtil.e(cardJso)
|
||||||
val result = NetworkApi.createCustomer(rsaKey, userId, userName, email,paymentMethodID)
|
val result = NetworkApi.createCustomer(rsaKey, userId, userName, email, paymentMethodID)
|
||||||
mSubscriptionCustomerLiveData.postValue(result)
|
mSubscriptionCustomerLiveData.postValue(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,12 +37,17 @@
|
|||||||
app:qmui_radius="@dimen/dp_64"
|
app:qmui_radius="@dimen/dp_64"
|
||||||
app:typeface="@string/roboto_bold_font" />
|
app:typeface="@string/roboto_bold_font" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/il_credit_card_payment_no_data"
|
||||||
|
android:visibility="gone"
|
||||||
|
layout="@layout/layout_credit_card_no_data" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rv_credit_card_payment_list"
|
android:id="@+id/rv_credit_card_payment_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_above="@id/btn_make_payment_credit_card"
|
android:layout_above="@id/btn_make_payment_credit_card"
|
||||||
android:layout_below="@id/btn_credit_card_payment_add"
|
android:layout_below="@id/btn_credit_card_payment_add"
|
||||||
android:layout_marginTop="@dimen/dp_12" />
|
android:layout_marginTop="@dimen/dp_12"
|
||||||
|
android:visibility="gone" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
<!-- 解决 Android P 禁用 http 请求的问题 -->
|
<!-- 解决 Android P 禁用 http 请求的问题 -->
|
||||||
<network-security-config>
|
<network-security-config>
|
||||||
<!-- 允许明文通信 -->
|
<!-- 允许明文通信 -->
|
||||||
<base-config cleartextTrafficPermitted="true" />
|
<base-config cleartextTrafficPermitted="false" />
|
||||||
</network-security-config>
|
</network-security-config>
|
||||||
@@ -15,84 +15,90 @@ object MMKVUtil {
|
|||||||
MMKV.initialize(application)
|
MMKV.initialize(application)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getMMKV(): MMKV {
|
||||||
|
return MMKV.defaultMMKV(MMKV.SINGLE_PROCESS_MODE, Utils.SECRET_KEY, true)
|
||||||
|
}
|
||||||
|
|
||||||
fun putBoolean(@MMKVKey key: String, value: Boolean) {
|
fun putBoolean(@MMKVKey key: String, value: Boolean) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBoolean(@MMKVKey key: String, defaultValue: Boolean = false): Boolean {
|
fun getBoolean(@MMKVKey key: String, defaultValue: Boolean = false): Boolean {
|
||||||
return MMKV.defaultMMKV().decodeBool(key, defaultValue)
|
return getMMKV().decodeBool(key, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putString(@MMKVKey key: String, value: String) {
|
fun putString(@MMKVKey key: String, value: String) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getString(@MMKVKey key: String, defaultValue: String = ""): String {
|
fun getString(@MMKVKey key: String, defaultValue: String = ""): String {
|
||||||
return MMKV.defaultMMKV().decodeString(key, defaultValue)!!
|
return getMMKV().decodeString(key, defaultValue)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putInt(@MMKVKey key: String, value: Int) {
|
fun putInt(@MMKVKey key: String, value: Int) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getInt(@MMKVKey key: String, defaultValue: Int = 0): Int {
|
fun getInt(@MMKVKey key: String, defaultValue: Int = 0): Int {
|
||||||
return MMKV.defaultMMKV().decodeInt(key, defaultValue)
|
return getMMKV().decodeInt(key, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putFloat(@MMKVKey key: String, value: Float) {
|
fun putFloat(@MMKVKey key: String, value: Float) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFloat(@MMKVKey key: String, defaultValue: Float = 0F): Float {
|
fun getFloat(@MMKVKey key: String, defaultValue: Float = 0F): Float {
|
||||||
return MMKV.defaultMMKV().decodeFloat(key, defaultValue)
|
return getMMKV().decodeFloat(key, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putLong(@MMKVKey key: String, value: Long) {
|
fun putLong(@MMKVKey key: String, value: Long) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLong(@MMKVKey key: String, defaultValue: Long = 0L): Long {
|
fun getLong(@MMKVKey key: String, defaultValue: Long = 0L): Long {
|
||||||
return MMKV.defaultMMKV().decodeLong(key, defaultValue)
|
return getMMKV().decodeLong(key, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putDouble(@MMKVKey key: String, value: Double) {
|
fun putDouble(@MMKVKey key: String, value: Double) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDouble(@MMKVKey key: String, defaultValue: Double = 0.0): Double {
|
fun getDouble(@MMKVKey key: String, defaultValue: Double = 0.0): Double {
|
||||||
return MMKV.defaultMMKV().decodeDouble(key, defaultValue)
|
return getMMKV().decodeDouble(key, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putByteArray(@MMKVKey key: String, value: ByteArray) {
|
fun putByteArray(@MMKVKey key: String, value: ByteArray) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getByteArray(@MMKVKey key: String, defaultValue: ByteArray = ByteArray(0)): ByteArray {
|
fun getByteArray(@MMKVKey key: String, defaultValue: ByteArray = ByteArray(0)): ByteArray {
|
||||||
return MMKV.defaultMMKV().decodeBytes(key, defaultValue)!!
|
return getMMKV().decodeBytes(key, defaultValue)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putStringSet(@MMKVKey key: String, value: Set<String>) {
|
fun putStringSet(@MMKVKey key: String, value: Set<String>) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStringSet(@MMKVKey key: String,
|
fun getStringSet(
|
||||||
defaultValue: Set<String> = mutableSetOf()): Set<String> {
|
@MMKVKey key: String,
|
||||||
return MMKV.defaultMMKV().decodeStringSet(key, defaultValue)!!
|
defaultValue: Set<String> = mutableSetOf()
|
||||||
|
): Set<String> {
|
||||||
|
return getMMKV().decodeStringSet(key, defaultValue)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putParcelable(@MMKVKey key: String, value: Parcelable) {
|
fun putParcelable(@MMKVKey key: String, value: Parcelable) {
|
||||||
MMKV.defaultMMKV().encode(key, value)
|
getMMKV().encode(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
//清空所有sp
|
//清空所有sp
|
||||||
fun clearAll() {
|
fun clearAll() {
|
||||||
//正式测试标识不清空
|
//正式测试标识不清空
|
||||||
val debugIp = getBoolean(MMKVKey.DebugIp, true)
|
val debugIp = getBoolean(MMKVKey.DebugIp, true)
|
||||||
MMKV.defaultMMKV().clearAll()
|
getMMKV().clearAll()
|
||||||
putBoolean(MMKVKey.DebugIp, debugIp)
|
putBoolean(MMKVKey.DebugIp, debugIp)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : Parcelable> getParcelable(@MMKVKey key: String): T? {
|
inline fun <reified T : Parcelable> getParcelable(@MMKVKey key: String): T? {
|
||||||
return MMKV.defaultMMKV().decodeParcelable(key, T::class.java)
|
return getMMKV().decodeParcelable(key, T::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,6 +30,7 @@ class Utils {
|
|||||||
|
|
||||||
//HTTP请求加密key
|
//HTTP请求加密key
|
||||||
var SECRET_KEY = ""
|
var SECRET_KEY = ""
|
||||||
|
val CARD_RSA_KEY="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAofuJbnkwyF7SWg3eRadSYT+ttfHN+CUmCzH0WW1EWTUQOG+01Nv8ux+UJUlxbZA2X7959Et/+VKE03+4OY0/26dlgkROMlXCUnzsucuaoHW+9whGi6xklRZrDLi22QBae/8XV1YDEU2vfYXtcvwf66J0t+bRIhGytQUZvUrL7OEaAHvwJU0QwCy3wQGWcCgSkPpDruIe4ar19iZMleE+BdPGIfKfVdPvWFls63g1eMFECb8F9zN6ydGTCvlqvx/4gfDuFQnF+JuTSre8euSpTRTQn/Q0s3K6KiROVcAYCqDW6cKxNUr2ha1C9ZFxMws9C0qhx5wYzfSlIjFthPC1qwIDAQAB"
|
||||||
const val DATE_FORMAT_PATTERN_CN = "yyyy-MM-dd"
|
const val DATE_FORMAT_PATTERN_CN = "yyyy-MM-dd"
|
||||||
const val DATE_FORMAT_PATTERN_CN2 = "yyyy-MM-dd HH:mm:ss"
|
const val DATE_FORMAT_PATTERN_CN2 = "yyyy-MM-dd HH:mm:ss"
|
||||||
const val DATE_FORMAT_PATTERN_CN3 = "yyyy/MM/dd HH:mm:ss"
|
const val DATE_FORMAT_PATTERN_CN3 = "yyyy/MM/dd HH:mm:ss"
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="false"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:supportsRtl="true">
|
android:supportsRtl="true">
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.content.ContentUris;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.DatabaseUtils;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
@@ -37,7 +36,6 @@ public class FileUtils {
|
|||||||
* TAG for log messages.
|
* TAG for log messages.
|
||||||
*/
|
*/
|
||||||
static final String TAG = "FileUtils";
|
static final String TAG = "FileUtils";
|
||||||
private static final boolean DEBUG = false; // Set to true to enable logging
|
|
||||||
/**
|
/**
|
||||||
* File and folder comparator. TODO Expose sorting option method
|
* File and folder comparator. TODO Expose sorting option method
|
||||||
*/
|
*/
|
||||||
@@ -216,7 +214,7 @@ public class FileUtils {
|
|||||||
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs
|
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs
|
||||||
, null);
|
, null);
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
if (DEBUG) DatabaseUtils.dumpCursor(cursor);
|
// if (DEBUG) DatabaseUtils.dumpCursor(cursor);
|
||||||
|
|
||||||
final int column_index = cursor.getColumnIndexOrThrow(column);
|
final int column_index = cursor.getColumnIndexOrThrow(column);
|
||||||
return cursor.getString(column_index);
|
return cursor.getString(column_index);
|
||||||
@@ -248,12 +246,12 @@ public class FileUtils {
|
|||||||
|
|
||||||
private static String getLocalPath(final Context context, final Uri uri) {
|
private static String getLocalPath(final Context context, final Uri uri) {
|
||||||
|
|
||||||
if (DEBUG)
|
// if (DEBUG)
|
||||||
Log.d(TAG + " File -",
|
// Log.d(TAG + " File -",
|
||||||
"Authority: " + uri.getAuthority() + ", Fragment: " + uri.getFragment() + ", "
|
// "Authority: " + uri.getAuthority() + ", Fragment: " + uri.getFragment() + ", "
|
||||||
+ "Port: " + uri.getPort() + ", Query: " + uri.getQuery() + ", Scheme"
|
// + "Port: " + uri.getPort() + ", Query: " + uri.getQuery() + ", Scheme"
|
||||||
+ ": " + uri.getScheme() + ", Host: " + uri.getHost() + ", Segments: "
|
// + ": " + uri.getScheme() + ", Host: " + uri.getHost() + ", Segments: "
|
||||||
+ uri.getPathSegments().toString());
|
// + uri.getPathSegments().toString());
|
||||||
|
|
||||||
|
|
||||||
// DocumentProvider
|
// DocumentProvider
|
||||||
@@ -487,12 +485,12 @@ public class FileUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void logDir(File dir) {
|
private static void logDir(File dir) {
|
||||||
if (!DEBUG) return;
|
// if (!DEBUG) return;
|
||||||
Log.d(TAG, "Dir=" + dir);
|
// Log.d(TAG, "Dir=" + dir);
|
||||||
File[] files = dir.listFiles();
|
// File[] files = dir.listFiles();
|
||||||
for (File file : files) {
|
// for (File file : files) {
|
||||||
Log.d(TAG, "File=" + file.getPath());
|
// Log.d(TAG, "File=" + file.getPath());
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
Reference in New Issue
Block a user