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>
|
||||
<SelectionState runConfigName="app">
|
||||
<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">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=3A251FDJH000CE" />
|
||||
|
||||
@@ -28,9 +28,9 @@ android {
|
||||
applicationId "com.abbidot.tracker"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 35
|
||||
versionCode 2214
|
||||
// versionName "2.2.14"
|
||||
versionName "2.2.14-Beta1"
|
||||
versionCode 2215
|
||||
// versionName "2.2.15"
|
||||
versionName "2.2.15-Beta1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
||||
177
app/proguard-rules.pro
vendored
177
app/proguard-rules.pro
vendored
@@ -23,12 +23,175 @@
|
||||
|
||||
|
||||
#禁用所有优化规则,查看混淆后 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.
|
||||
-dontwarn com.baidu.mapsdkplatform.comapi.util.SysOSAPI
|
||||
-dontwarn com.daimajia.easing.Glider
|
||||
-dontwarn com.daimajia.easing.Skill
|
||||
# 基础混淆配置
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-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.BLUETOOTH_ADMIN" /> <!-- 获取模拟定位信息 -->
|
||||
<uses-permission
|
||||
android:name="android.permission.ACCESS_MOCK_LOCATION"
|
||||
tools:ignore="MockLocation,ProtectedPermissions" />
|
||||
<!-- <uses-permission-->
|
||||
<!-- android:name="android.permission.ACCESS_MOCK_LOCATION"-->
|
||||
<!-- tools:ignore="MockLocation,ProtectedPermissions" />-->
|
||||
|
||||
<permission
|
||||
android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
|
||||
@@ -95,7 +95,8 @@
|
||||
|
||||
<application
|
||||
android:name=".MyApplication"
|
||||
android:allowBackup="true"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:icon="@mipmap/logo_abbidot"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
|
||||
@@ -578,10 +578,11 @@ abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInfl
|
||||
fun <T> dealRequestResult(
|
||||
it: Result<T>,
|
||||
getResultCallback: GetResultCallback,
|
||||
showLoading: Boolean = false,
|
||||
isShowNoDataTip: Boolean = true,
|
||||
isShowRequestErrorTip: Boolean = true,
|
||||
isShowCodeError: Boolean = true,
|
||||
showLoading: Boolean = false,//是否显示loading弹窗
|
||||
isShowNoDataTip: Boolean = true,//是否显示无数据提示
|
||||
isShowRequestErrorTip: Boolean = true,//是否显示请求错误提示
|
||||
isShowCodeError: Boolean = true,//是否显示错误码提示
|
||||
isShowNetCodeMsg: Boolean = false,//是否显示服务器返回message提示
|
||||
errorTip: String = getString(R.string.txt_net_error)
|
||||
) {
|
||||
try {
|
||||
@@ -614,7 +615,9 @@ abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInfl
|
||||
|
||||
val data = it.getOrNull()
|
||||
if (null == data) {
|
||||
if (isShowRequestErrorTip) {
|
||||
if (isShowNetCodeMsg && exceptionCode == ErrorCode.ERROR.toString()) {
|
||||
showToast(exceptionMessage ?: errorTip)
|
||||
} else if (isShowRequestErrorTip) {
|
||||
if (NetworkUtil.isNetworkAvailable(mContext)) {
|
||||
showToast(errorTip)
|
||||
} else {
|
||||
|
||||
@@ -179,10 +179,11 @@ abstract class BaseFragment<T : ViewBinding>(
|
||||
fun <T> dealRequestResult(
|
||||
it: Result<T>,
|
||||
getResultCallback: GetResultCallback,
|
||||
showLoading: Boolean = false,
|
||||
isShowNoDataTip: Boolean = true,
|
||||
isRequestErrorTip: Boolean = true,
|
||||
isShowCodeError: Boolean = true,
|
||||
showLoading: Boolean = false,//是否显示loading弹窗
|
||||
isShowNoDataTip: Boolean = true,//是否显示无数据提示
|
||||
isRequestErrorTip: Boolean = true,//是否显示请求错误提示
|
||||
isShowCodeError: Boolean = true,//是否显示错误码提示
|
||||
isShowNetCodeMsg: Boolean = false,//是否显示服务器返回message提示
|
||||
errorTip: String = getString(R.string.txt_net_error)
|
||||
) {
|
||||
(activity as BaseActivity<*>).dealRequestResult(
|
||||
@@ -191,8 +192,8 @@ abstract class BaseFragment<T : ViewBinding>(
|
||||
showLoading,
|
||||
isShowNoDataTip,
|
||||
isRequestErrorTip,
|
||||
isShowCodeError,
|
||||
errorTip
|
||||
isShowCodeError, isShowNetCodeMsg,
|
||||
errorTip,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ abstract class MyDatabase : RoomDatabase() {
|
||||
private val db: MyDatabase by lazy {
|
||||
Room.databaseBuilder(MyApplication.instance, MyDatabase::class.java, "tracker_dp")
|
||||
// .addMigrations(MIGRATION_1_2)
|
||||
.fallbackToDestructiveMigration()//删除旧表格并创建新表格,的方式升级数据库版本
|
||||
.fallbackToDestructiveMigration(true)//删除旧表格并创建新表格,的方式升级数据库版本
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package com.abbidot.tracker.database.dao
|
||||
|
||||
import android.util.Log
|
||||
import androidx.room.*
|
||||
import androidx.room.Delete
|
||||
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.SupportSQLiteQuery
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
|
||||
/**
|
||||
*Created by .yzq on 2022/4/1/001.
|
||||
@@ -28,43 +32,43 @@ interface BaseDao<T> {
|
||||
* OnConflictStrategy.REPLACE新数据替换旧数据
|
||||
*/
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(obj: T): Long
|
||||
fun insert(obj: T): Long
|
||||
|
||||
/**
|
||||
* 添加数组对象数据
|
||||
*/
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(vararg objs: T): LongArray?
|
||||
fun insert(vararg objs: T): LongArray?
|
||||
|
||||
/**
|
||||
* 添加对象集合
|
||||
*/
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(personList: List<T>): List<Long>
|
||||
fun insert(personList: List<T>): List<Long>
|
||||
|
||||
/**
|
||||
* 根据对象中的主键删除(主键是自动增长的,无需手动赋值)
|
||||
*/
|
||||
@Delete
|
||||
fun delete(obj: T)
|
||||
fun delete(obj: T)
|
||||
|
||||
/**
|
||||
* 根据对象中的主键更新(主键是自动增长的,无需手动赋值)
|
||||
*/
|
||||
@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")
|
||||
return doDeleteAll(query)
|
||||
}
|
||||
|
||||
fun findAll(tableName:String): List<T>? {
|
||||
fun findAll(tableName: String): List<T>? {
|
||||
val query = SimpleSQLiteQuery("select * from $tableName")
|
||||
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))
|
||||
return doFind(query)
|
||||
}
|
||||
@@ -73,9 +77,9 @@ interface BaseDao<T> {
|
||||
* [params] 列名
|
||||
* [value] 列的值
|
||||
*/
|
||||
fun deleteByParams(params: String, value: String,tableName:String): Int {
|
||||
val query = SimpleSQLiteQuery("delete from $tableName where $params='${value}'")
|
||||
Log.d("ez", "deleteByParams: ${"delete from $tableName where $params='${value}'"}")
|
||||
fun deleteByParams(params: String, value: String, tableName: String): Int {
|
||||
val query = SimpleSQLiteQuery("delete from $tableName where $params= ?", arrayOf(value))
|
||||
LogUtil.d("ez", "deleteByParams: ${"delete from $tableName where $params = ?"}")
|
||||
return doDeleteByParams(query)
|
||||
}
|
||||
|
||||
@@ -83,18 +87,26 @@ interface BaseDao<T> {
|
||||
* 分页查询,支持传入多个字段,但必须要按照顺序传入
|
||||
* 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(
|
||||
"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)
|
||||
}
|
||||
|
||||
/**
|
||||
* 降序分页查询
|
||||
*/
|
||||
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(
|
||||
"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)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.base.BaseActivity
|
||||
import com.abbidot.tracker.bean.CreditCardBean
|
||||
import com.abbidot.tracker.constant.ConstantString
|
||||
import com.abbidot.tracker.database.MyDatabase
|
||||
import com.abbidot.tracker.databinding.ActivityAddCreditCardBinding
|
||||
import com.abbidot.tracker.util.Util
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -123,7 +122,7 @@ class AddCreditCardActivity :
|
||||
card.firstName = firstName
|
||||
card.expirationDate = creditCardValidity
|
||||
card.cvv = cvv
|
||||
MyDatabase.creditCardDao().insert(card)
|
||||
// MyDatabase.creditCardDao().insert(card)
|
||||
runOnUiThread {
|
||||
val intent = Intent()
|
||||
intent.putExtra(ConstantString.Card, card)
|
||||
|
||||
@@ -20,16 +20,13 @@ import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.base.BaseActivity
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.constant.GetResultCallback
|
||||
import com.abbidot.tracker.database.MyDatabase
|
||||
import com.abbidot.tracker.databinding.ActivityLoginV2Binding
|
||||
import com.abbidot.tracker.ui.activity.set.FirstPermissionsActivity
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.vm.LoginViewModel
|
||||
import com.abbidot.tracker.vm.TrackerInfoViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class LoginV2Activity : BaseActivity<ActivityLoginV2Binding>(ActivityLoginV2Binding::inflate) {
|
||||
|
||||
@@ -136,14 +133,14 @@ class LoginV2Activity : BaseActivity<ActivityLoginV2Binding>(ActivityLoginV2Bind
|
||||
)
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.IO) {
|
||||
//保存本地数据库
|
||||
for (device in list) {
|
||||
if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
||||
MyDatabase.deviceDao().insert(device)
|
||||
}
|
||||
}
|
||||
}
|
||||
// withContext(Dispatchers.IO) {
|
||||
// //保存本地数据库
|
||||
// for (device in list) {
|
||||
// if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
||||
// MyDatabase.deviceDao().insert(device)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
showToast(R.string.txt_login_successful, gravity = Gravity.CENTER)
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ class MyTrackerV2Activity :
|
||||
//保存本地数据库
|
||||
if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
||||
bindDeviceNumber++
|
||||
MyDatabase.deviceDao().insert(device)
|
||||
// MyDatabase.deviceDao().insert(device)
|
||||
} else if (!TextUtils.isEmpty(device.deviceOutId) && null == device.pet) {
|
||||
//删除本地没绑定的设备
|
||||
MyDatabase.deviceDao().deleteByParams(
|
||||
|
||||
@@ -118,18 +118,18 @@ class FirstPetProfileActivity :
|
||||
mTrackerViewModel.getDeviceListLiveData.observe(this) {
|
||||
dealRequestResult(it, object : GetResultCallback {
|
||||
override fun onResult(any: Any) {
|
||||
it.getOrNull()?.let { list ->
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
for (device in list) {
|
||||
//保存本地数据库
|
||||
if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
||||
MyDatabase.deviceDao().insert(device)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// it.getOrNull()?.let { list ->
|
||||
// lifecycleScope.launch {
|
||||
// withContext(Dispatchers.IO) {
|
||||
// for (device in list) {
|
||||
// //保存本地数据库
|
||||
// if (!TextUtils.isEmpty(device.deviceOutId) && null != device.pet) {
|
||||
// MyDatabase.deviceDao().insert(device)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
showToast(R.string.txt_bind_success, isFinish = true)
|
||||
mViewBinding.root.postDelayed({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.abbidot.tracker.ui.activity.subscribe
|
||||
|
||||
import android.content.Intent
|
||||
import android.text.InputFilter
|
||||
import android.text.InputFilter.LengthFilter
|
||||
import android.text.InputType
|
||||
@@ -143,7 +144,7 @@ class AddCreditCardPaymentActivity :
|
||||
override fun onRequestError(exceptionCode: String?) {
|
||||
setButtonEnabled(mViewBinding.btnSaveNewCreditCard, ConstantInt.Type1)
|
||||
}
|
||||
})
|
||||
}, isShowNetCodeMsg = true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +337,7 @@ class AddCreditCardPaymentActivity :
|
||||
it.cardName = cardName
|
||||
it.expirationDate = creditCardValidity
|
||||
it.cvv = cvv
|
||||
MyDatabase.creditCardDao().insert(it)
|
||||
// MyDatabase.creditCardDao().insert(it)
|
||||
}
|
||||
|
||||
runOnUiThread {
|
||||
@@ -410,28 +411,21 @@ class AddCreditCardPaymentActivity :
|
||||
|
||||
override fun onSuccess(result: PaymentMethod) {
|
||||
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}"
|
||||
mSubscriptionPayViewModel.savePaymentMethodInfo(
|
||||
paymentMethodID
|
||||
)
|
||||
mSubscriptionPayViewModel.savePaymentMethodInfo(paymentMethodID)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
MyDatabase.creditCardDao().deleteAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||
// MyDatabase.creditCardDao().deleteAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||
it.cardNumber = cardNumber
|
||||
it.cardName = cardName
|
||||
it.expirationDate = creditCardValidity
|
||||
it.cvv = cvv
|
||||
MyDatabase.creditCardDao().insert(it)
|
||||
// MyDatabase.creditCardDao().insert(it)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.abbidot.baselibrary.constant.ResultCode
|
||||
import com.abbidot.baselibrary.list.BaseRecyclerAdapter
|
||||
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.constant.ConstantString
|
||||
import com.abbidot.tracker.constant.GetResultCallback
|
||||
import com.abbidot.tracker.database.MyDatabase
|
||||
import com.abbidot.tracker.databinding.FragmentCreditCardPaymentBinding
|
||||
import com.abbidot.tracker.ui.activity.subscribe.AddCreditCardPaymentActivity
|
||||
import com.abbidot.tracker.ui.activity.subscribe.PaymentMethodActivity
|
||||
import com.abbidot.tracker.ui.activity.subscribe.PaymentSuccessActivity
|
||||
import com.abbidot.tracker.util.ThirdPartyUtil
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.vm.SubscriptionPayViewModel
|
||||
import com.stripe.android.ApiResultCallback
|
||||
import com.stripe.android.Stripe
|
||||
import com.stripe.android.model.PaymentMethod
|
||||
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)
|
||||
)
|
||||
|
||||
ilCreditCardPaymentNoData.btnSureSubscribePlan1Continue.visibility = View.GONE
|
||||
setOnClickListenerViews(btnCreditCardPaymentAdd, btnMakePaymentCreditCard)
|
||||
}
|
||||
// getCardData()
|
||||
@@ -94,17 +92,28 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
||||
|
||||
fun getCardData(stripeMethodInfo: CreditCardBean) {
|
||||
if (TextUtils.isEmpty(stripeMethodInfo.lastFourNumber)) {
|
||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||
val list = MyDatabase.creditCardDao().findAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||
list?.let {
|
||||
mActivity?.runOnUiThread {
|
||||
val sortedByList =
|
||||
list.sortedByDescending { l -> l.isPrimary }.toMutableList()
|
||||
setCheckAndPrimaryState(sortedByList)
|
||||
mCreditCardAdapter.setData(sortedByList, true)
|
||||
}
|
||||
// viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||
// val list = MyDatabase.creditCardDao().findAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||
// list?.let {
|
||||
// mActivity?.runOnUiThread {
|
||||
// val sortedByList =
|
||||
// list.sortedByDescending { l -> l.isPrimary }.toMutableList()
|
||||
// setCheckAndPrimaryState(sortedByList)
|
||||
// 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 {
|
||||
stripeMethodInfo.apply {
|
||||
expirationDate = "$expMonth/$expYear"
|
||||
@@ -127,8 +136,9 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
||||
add(stripeMethodInfo)
|
||||
mCreditCardAdapter.setData(this, true)
|
||||
}
|
||||
mViewBinding.ilCreditCardPaymentNoData.root.visibility = View.GONE
|
||||
ViewUtil.instance.viewShow(mViewBinding.rvCreditCardPaymentList)
|
||||
}
|
||||
ViewUtil.instance.viewShow(mViewBinding.rvCreditCardPaymentList)
|
||||
}
|
||||
|
||||
fun goEditCard(cardBean: CreditCardBean) {
|
||||
@@ -162,7 +172,7 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
||||
override fun onRequestError(exceptionCode: String?) {
|
||||
showNoCancelableLoading(false)
|
||||
}
|
||||
})
|
||||
}, isShowNetCodeMsg = true)
|
||||
}
|
||||
|
||||
mCreateStripeOrderLiveData.observe(viewLifecycleOwner) {
|
||||
@@ -245,7 +255,19 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
||||
// }
|
||||
if (it.resultCode == ResultCode.ResultCode_1) {
|
||||
// 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 {
|
||||
|
||||
private val iP = "3.101.8.36"
|
||||
// private val iP = "192.168.0.69"
|
||||
private val iP = ""
|
||||
|
||||
//默认国外服务器端口
|
||||
private var port = 8868
|
||||
private var port = 0
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
private val crcTable = ushortArrayOf(
|
||||
@@ -51,7 +50,7 @@ class SocketUtilManage {
|
||||
fun initEasySocket(context: Context) {
|
||||
if (AppUtils.isChina()) {
|
||||
//国内socket端口号
|
||||
port = 9168
|
||||
port = 1
|
||||
}
|
||||
//socket配置
|
||||
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.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.baselibrary.util.Utils
|
||||
import com.abbidot.baselibrary.util.rsa.RSA
|
||||
import com.abbidot.tracker.bean.CreditCardBean
|
||||
import com.abbidot.tracker.bean.PayResultBean
|
||||
@@ -33,7 +34,7 @@ class SubscriptionPayViewModel : ViewModel() {
|
||||
/**
|
||||
* Stripe支付创建消费用户
|
||||
*/
|
||||
fun createCustomer(card: CreditCardBean,paymentMethodID: String) {
|
||||
fun createCustomer(card: CreditCardBean, paymentMethodID: String) {
|
||||
// activity.showLoading(true)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val userId = MMKVUtil.getString(MMKVKey.UserId)
|
||||
@@ -48,12 +49,10 @@ class SubscriptionPayViewModel : ViewModel() {
|
||||
cardParamsMap["cardName"] = card.cardName
|
||||
cardParamsMap["cardnum"] = card.cardNumber
|
||||
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)
|
||||
val result = NetworkApi.createCustomer(rsaKey, userId, userName, email,paymentMethodID)
|
||||
val result = NetworkApi.createCustomer(rsaKey, userId, userName, email, paymentMethodID)
|
||||
mSubscriptionCustomerLiveData.postValue(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,12 +37,17 @@
|
||||
app:qmui_radius="@dimen/dp_64"
|
||||
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
|
||||
android:id="@+id/rv_credit_card_payment_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_above="@id/btn_make_payment_credit_card"
|
||||
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>
|
||||
@@ -2,5 +2,5 @@
|
||||
<!-- 解决 Android P 禁用 http 请求的问题 -->
|
||||
<network-security-config>
|
||||
<!-- 允许明文通信 -->
|
||||
<base-config cleartextTrafficPermitted="true" />
|
||||
<base-config cleartextTrafficPermitted="false" />
|
||||
</network-security-config>
|
||||
@@ -15,84 +15,90 @@ object MMKVUtil {
|
||||
MMKV.initialize(application)
|
||||
}
|
||||
|
||||
fun getMMKV(): MMKV {
|
||||
return MMKV.defaultMMKV(MMKV.SINGLE_PROCESS_MODE, Utils.SECRET_KEY, true)
|
||||
}
|
||||
|
||||
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 {
|
||||
return MMKV.defaultMMKV().decodeBool(key, defaultValue)
|
||||
return getMMKV().decodeBool(key, defaultValue)
|
||||
}
|
||||
|
||||
fun putString(@MMKVKey key: String, value: String) {
|
||||
MMKV.defaultMMKV().encode(key, value)
|
||||
getMMKV().encode(key, value)
|
||||
}
|
||||
|
||||
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) {
|
||||
MMKV.defaultMMKV().encode(key, value)
|
||||
getMMKV().encode(key, value)
|
||||
}
|
||||
|
||||
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) {
|
||||
MMKV.defaultMMKV().encode(key, value)
|
||||
getMMKV().encode(key, value)
|
||||
}
|
||||
|
||||
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) {
|
||||
MMKV.defaultMMKV().encode(key, value)
|
||||
getMMKV().encode(key, value)
|
||||
}
|
||||
|
||||
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) {
|
||||
MMKV.defaultMMKV().encode(key, value)
|
||||
getMMKV().encode(key, value)
|
||||
}
|
||||
|
||||
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) {
|
||||
MMKV.defaultMMKV().encode(key, value)
|
||||
getMMKV().encode(key, value)
|
||||
}
|
||||
|
||||
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>) {
|
||||
MMKV.defaultMMKV().encode(key, value)
|
||||
getMMKV().encode(key, value)
|
||||
}
|
||||
|
||||
fun getStringSet(@MMKVKey key: String,
|
||||
defaultValue: Set<String> = mutableSetOf()): Set<String> {
|
||||
return MMKV.defaultMMKV().decodeStringSet(key, defaultValue)!!
|
||||
fun getStringSet(
|
||||
@MMKVKey key: String,
|
||||
defaultValue: Set<String> = mutableSetOf()
|
||||
): Set<String> {
|
||||
return getMMKV().decodeStringSet(key, defaultValue)!!
|
||||
}
|
||||
|
||||
fun putParcelable(@MMKVKey key: String, value: Parcelable) {
|
||||
MMKV.defaultMMKV().encode(key, value)
|
||||
getMMKV().encode(key, value)
|
||||
}
|
||||
|
||||
//清空所有sp
|
||||
fun clearAll() {
|
||||
//正式测试标识不清空
|
||||
val debugIp = getBoolean(MMKVKey.DebugIp, true)
|
||||
MMKV.defaultMMKV().clearAll()
|
||||
getMMKV().clearAll()
|
||||
putBoolean(MMKVKey.DebugIp, debugIp)
|
||||
}
|
||||
|
||||
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
|
||||
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_CN2 = "yyyy-MM-dd HH:mm:ss"
|
||||
const val DATE_FORMAT_PATTERN_CN3 = "yyyy/MM/dd HH:mm:ss"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:allowBackup="false"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:supportsRtl="true">
|
||||
<activity
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
@@ -37,7 +36,6 @@ public class FileUtils {
|
||||
* TAG for log messages.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@@ -216,7 +214,7 @@ public class FileUtils {
|
||||
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs
|
||||
, null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
if (DEBUG) DatabaseUtils.dumpCursor(cursor);
|
||||
// if (DEBUG) DatabaseUtils.dumpCursor(cursor);
|
||||
|
||||
final int column_index = cursor.getColumnIndexOrThrow(column);
|
||||
return cursor.getString(column_index);
|
||||
@@ -248,12 +246,12 @@ public class FileUtils {
|
||||
|
||||
private static String getLocalPath(final Context context, final Uri uri) {
|
||||
|
||||
if (DEBUG)
|
||||
Log.d(TAG + " File -",
|
||||
"Authority: " + uri.getAuthority() + ", Fragment: " + uri.getFragment() + ", "
|
||||
+ "Port: " + uri.getPort() + ", Query: " + uri.getQuery() + ", Scheme"
|
||||
+ ": " + uri.getScheme() + ", Host: " + uri.getHost() + ", Segments: "
|
||||
+ uri.getPathSegments().toString());
|
||||
// if (DEBUG)
|
||||
// Log.d(TAG + " File -",
|
||||
// "Authority: " + uri.getAuthority() + ", Fragment: " + uri.getFragment() + ", "
|
||||
// + "Port: " + uri.getPort() + ", Query: " + uri.getQuery() + ", Scheme"
|
||||
// + ": " + uri.getScheme() + ", Host: " + uri.getHost() + ", Segments: "
|
||||
// + uri.getPathSegments().toString());
|
||||
|
||||
|
||||
// DocumentProvider
|
||||
@@ -487,12 +485,12 @@ public class FileUtils {
|
||||
}
|
||||
|
||||
private static void logDir(File dir) {
|
||||
if (!DEBUG) return;
|
||||
Log.d(TAG, "Dir=" + dir);
|
||||
File[] files = dir.listFiles();
|
||||
for (File file : files) {
|
||||
Log.d(TAG, "File=" + file.getPath());
|
||||
}
|
||||
// if (!DEBUG) return;
|
||||
// Log.d(TAG, "Dir=" + dir);
|
||||
// File[] files = dir.listFiles();
|
||||
// for (File file : files) {
|
||||
// Log.d(TAG, "File=" + file.getPath());
|
||||
// }
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user