This commit is contained in:
litingting 2024-07-02 15:16:49 +08:00
commit 888deb17e8
98 changed files with 3400 additions and 0 deletions

47
.gitignore vendored Normal file
View File

@ -0,0 +1,47 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
/.safedk/dex/android-support-multidex.dex
/app/release/baselineProfiles/0/app-release.dm
/app/release/baselineProfiles/1/app-release.dm
/app/release/AppLock Defender1.0(1).aab
/.safedk/list.enc
/app/release/output-metadata.json
/.safedk/proguard-safedk.pro
/.safedk/dex/SafeDKAndroid-6.2.5.dex
/.safedk/api/SafeDKAndroid-6.2.5.jar
gradle.properties
gradlew
gradlew.bat
.idea/.gitignore
.idea/.name
.idea/appInsightsSettings.xml
.idea/compiler.xml
.idea/dbnavigator.xml
.idea/deploymentTargetDropDown.xml
.idea/deploymentTargetSelector.xml
.idea/gradle.xml
.idea/kotlinc.xml
.idea/migrations.xml
.idea/misc.xml
.idea/vcs.xml
.safedk/app_sdks.lst
.safedk/hashes.safedk
.safedk/plugin.properties
.safedk/api/SafeDKAndroid-6.2.6.jar
.safedk/api/SafeDKAndroid-6.3.1.jar
.safedk/dex/SafeDKAndroid-6.3.1.dex
app/release/AppLock Defender1.1(2).aab
app/release/app-release.apk

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

74
app/build.gradle Normal file
View File

@ -0,0 +1,74 @@
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
id("kotlin-kapt")
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("applovin-quality-service")
}
applovin {
apiKey "gaubl3w6OhMaWqmJb15zVNMO8W91OOSTe2fnoftZMmDkQFTnwMdQVdOdPOMwLRbglPnJsKHfqoPl079qleMk96"
}
android {
namespace 'com.kitobochi.softapp.timberlock'
compileSdk 34
defaultConfig {
applicationId "com.applock.privacy.defender"
minSdk 22
targetSdk 34
versionCode 2
versionName "1.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation libs.androidx.core.ktx
implementation libs.androidx.appcompat
implementation libs.material
implementation libs.androidx.activity
implementation libs.androidx.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
kapt 'androidx.room:room-compiler:2.6.1'
implementation 'androidx.room:room-runtime:2.6.1'
implementation("androidx.room:room-ktx:2.6.1")
implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
implementation("com.google.firebase:firebase-analytics-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx")
implementation("com.applovin:applovin-sdk:+")
implementation("com.applovin.mediation:vungle-adapter:+")
implementation("com.applovin.mediation:bytedance-adapter:+")
implementation("com.applovin.mediation:mintegral-adapter:+")
}

29
app/google-services.json Normal file
View File

@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "36819996956",
"project_id": "applock-defender---security",
"storage_bucket": "applock-defender---security.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:36819996956:android:63137f1a9ab4d34a37ead9",
"android_client_info": {
"package_name": "com.applock.privacy.defender"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyBGf4ZJn19sNlDd8U1Qt9L9vOUfyNTlF8I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

6
app/info/info.txt Normal file
View File

@ -0,0 +1,6 @@
包名com.applock.privacy.defender
应用名AppLock Defender
别名key_applock_defender
keykey_applock_defender
passwordkey123456

Binary file not shown.

Binary file not shown.

35
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,35 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# room base
-keepclassmembers class * {
@androidx.room.Query <methods>;
}
-keepclassmembers class com.kitobochi.softapp.timberlock.db.AppDatabaseManager{
public static final java.lang.String DB_NAME;
public static final int DB_VERSION;
}
-keep class com.kitobochi.softapp.timberlock.db.AppDatabase { *; }
-keep class com.kitobochi.softapp.timberlock.db.AppDao { *; }
-keep class com.kitobochi.softapp.timberlock.db.AppEntity { *; }

View File

@ -0,0 +1,24 @@
package com.kitobochi.softapp.timberlock
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.kitobochi.softapp.timberlock", appContext.packageName)
}
}

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
</intent>
</queries>
<application
android:name=".App"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/icon_logo"
android:label="@string/app_name"
android:roundIcon="@mipmap/icon_logo"
android:supportsRtl="true"
android:theme="@style/Theme.TimberLock"
tools:targetApi="31">
<activity
android:name=".ui.activity.StartPageActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.activity.MainActivity" />
<activity android:name=".ui.activity.SetPwdActivity" />
<service android:name=".service.AppLockService" />
</application>
</manifest>

View File

@ -0,0 +1,88 @@
package com.kitobochi.softapp.timberlock
import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.applovin.sdk.AppLovinMediationProvider
import com.applovin.sdk.AppLovinSdk
import com.applovin.sdk.AppLovinSdkInitializationConfiguration
import com.kitobochi.softapp.timberlock.db.AppDatabase
import com.kitobochi.softapp.timberlock.db.AppEntity
import com.kitobochi.softapp.timberlock.tools.AppListManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class App : Application() {
private val spName = "share_name"
private val PWD_KEY = "locker_pwd"
val reqCodeUsage = 1
val reqCodeOverlays = 2
companion object {
lateinit var appContext: Context
lateinit var sp: SharedPreferences
lateinit var SpEditor: SharedPreferences.Editor
const val ADSDK = "2qIXFPBROAqtuAoW4uQ78MTqJTfXWGurGLpQvE0iae3vmVXLa8SMxnxgdtq9O1GU3qQVRR1EcHhpS74qiyL8CK"
const val AD_INIT = "on_success_action"
var initOK = false
var count = 0
}
override fun onCreate() {
super.onCreate()
appContext = this
initSp()
CoroutineScope(Dispatchers.IO).launch {
for (appEntity: AppEntity in AppDatabase.database.getAppDao().findApp()!!) {
val isNeedDelete = AppListManager().delUnInstallApp(appContext, appEntity.packageName)
if (isNeedDelete) {
AppDatabase.database.getAppDao().deleteData(appEntity)
}
}
}
val pwd = getPwd()
if (pwd.isEmpty()) {
AppListManager().getAppList(appContext, false)
} else {
AppListManager().getAppList(appContext, true)
}
initSDK()
}
private fun initSDK() {
val initConfig = AppLovinSdkInitializationConfiguration.builder(ADSDK, this)
.setMediationProvider(AppLovinMediationProvider.MAX)
.build()
AppLovinSdk.getInstance(this).initialize(initConfig){
initOK = true
LocalBroadcastManager.getInstance(this).sendBroadcast(Intent(AD_INIT))
}
AppLovinSdk.getInstance(this).settings.setVerboseLogging(true)
}
public fun updatePwd(pwd: String) {
SpEditor.putString(PWD_KEY, pwd)
SpEditor.apply()
}
public fun getPwd(): String {
return sp.getString(PWD_KEY, "")!!
}
private fun initSp() {
sp = App.appContext.getSharedPreferences(spName, Context.MODE_PRIVATE)
SpEditor = sp.edit()
}
}

View File

@ -0,0 +1,9 @@
package com.kitobochi.softapp.timberlock.ad
import com.applovin.mediation.MaxAd
interface AdListener {
fun onFail(ad: MaxAd)
fun onSuccess()
fun onHidden()
}

View File

@ -0,0 +1,78 @@
package com.kitobochi.softapp.timberlock.ad
import android.app.Activity
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxInterstitialAd
import com.kitobochi.softapp.timberlock.App
object AdManager {
private val one_AD = "02d8ee636a579373"
private val two_Ad = "02d8ee636a579373"
private val three_ad = "0b004d33e636f7f8"
private val list: MutableList<MaxInterstitialAd> = mutableListOf()
fun onCache(list: List<MaxInterstitialAd>): MaxInterstitialAd? {
list.shuffled()
for (ad in list) {
if (ad.isReady) {
return ad
}
}
return null
}
fun adLoad(): List<MaxInterstitialAd> {
if (list.isEmpty()) {
val ad_two = MaxInterstitialAd(two_Ad, App.appContext)
val ad_one = MaxInterstitialAd(one_AD, App.appContext)
val ad_three = MaxInterstitialAd(three_ad, App.appContext)
ad_two.loadAd()
ad_one.loadAd()
ad_three.loadAd()
list.add(ad_one)
list.add(ad_two)
list.add(ad_three)
}
for (ad: MaxInterstitialAd in list) {
if (!ad.isReady) {
ad.loadAd()
}
}
return list
}
fun setAdListener(ad: MaxInterstitialAd, listener: AdListener) {
ad.setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
}
override fun onAdDisplayed(p0: MaxAd) {
listener.onSuccess()
}
override fun onAdHidden(p0: MaxAd) {
listener.onHidden()
}
override fun onAdClicked(p0: MaxAd) {
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
listener.onFail(p0)
}
})
}
}

View File

@ -0,0 +1,5 @@
package com.kitobochi.softapp.timberlock.ad
interface AdMsgListener {
fun msg(msg: String)
}

View File

@ -0,0 +1,29 @@
package com.kitobochi.softapp.timberlock.db
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
@Dao
interface AppDao {
@Delete
fun deleteData(dataApp: AppEntity)
@Query("select * from t_data_app where packageName=:packName")
fun findByPackName(packName: String): AppEntity?
@Query("select * from t_data_app where isSyStem=:system AND isRecommend = :recommend")
fun findByType(system: Boolean, recommend: Boolean): List<AppEntity>?
@Update
fun updateData(dataApp: AppEntity)
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertData(dataApp: AppEntity)
@Query("select * from t_data_app")
fun findApp(): List<AppEntity>?
}

View File

@ -0,0 +1,27 @@
package com.kitobochi.softapp.timberlock.db
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.kitobochi.softapp.timberlock.App
@Database(
entities = [AppEntity::class],
version = AppDatabaseManager.DB_VERSION,
exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
companion object {
val database: AppDatabase by lazy {
getInstance()
}
private fun getInstance(): AppDatabase {
return Room.databaseBuilder(
App.appContext, AppDatabase::class.java, AppDatabaseManager.DB_NAME
).build()
}
}
abstract fun getAppDao(): AppDao
}

View File

@ -0,0 +1,7 @@
package com.kitobochi.softapp.timberlock.db
object AppDatabaseManager {
const val TABLE_NAME = "t_data_app"
const val DB_VERSION = 1
const val DB_NAME = "app_db"
}

View File

@ -0,0 +1,15 @@
package com.kitobochi.softapp.timberlock.db
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(tableName = AppDatabaseManager.TABLE_NAME, indices = [Index(value = ["packageName"], unique = true)])
data class AppEntity(
@PrimaryKey(autoGenerate = true) var id: Int = 0,
var packageName: String = "",
var appName: String = "",
var isLock: Boolean = false,
var isSyStem: Boolean = true,
var isRecommend: Boolean = false
)

View File

@ -0,0 +1,75 @@
package com.kitobochi.softapp.timberlock.service
import android.app.IntentService
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.kitobochi.softapp.timberlock.db.AppDatabase
import com.kitobochi.softapp.timberlock.tools.LockManager
import com.kitobochi.softapp.timberlock.tools.LockServiceManager
import java.util.Objects
class AppLockService(name: String? = "") : IntentService(name) {
private lateinit var instance: LockManager
private var lastLockPackName = ""
override fun onHandleIntent(intent: Intent?) {
instance = LockManager(this)
val isCheckTop: Boolean = true
while (isCheckTop) {
val packageName = LockServiceManager().checkUsageStats(this)
if (Objects.equals(packageName, "")) {
// Log.d("-------", "continue1")
// Log.d("-------", packageName)
continue
}
val appEntity = AppDatabase.database.getAppDao().findByPackName(packageName)
if (appEntity == null) {
val mainHandler = Handler(Looper.getMainLooper())
mainHandler.post(Runnable {
instance.unLock()
})
lastLockPackName = packageName
// Log.d("-------", "continue2")
continue
}
if (Objects.equals(packageName, lastLockPackName)) {
// Log.d("-------", "continue3")
continue
}
if (appEntity.isLock) {
if (!Objects.equals(packageName, lastLockPackName)) {
val mainHandler = Handler(Looper.getMainLooper())
mainHandler.post(Runnable {
instance.showLockView()
})
// Log.d("-------", "continue4")
} else {
}
} else {
val mainHandler = Handler(Looper.getMainLooper())
mainHandler.post(Runnable {
instance.unLock()
})
// Log.d("-------", "continue5")
}
lastLockPackName = packageName
}
}
}

View File

@ -0,0 +1,113 @@
package com.kitobochi.softapp.timberlock.tools
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import com.kitobochi.softapp.timberlock.db.AppDatabase
import com.kitobochi.softapp.timberlock.db.AppEntity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.Objects
class AppListManager {
private fun addDb(list: List<AppEntity>, isSystem: Boolean, isUpdate: Boolean) {
for (i in 0 until list.size) {
val appEntity = list[i]
appEntity.isSyStem = isSystem
if (isUpdate) {
val appEntity1 = AppDatabase.database.getAppDao().findByPackName(appEntity.packageName)
if (appEntity1 == null) {
AppDatabase.database.getAppDao().insertData(appEntity)
}
} else {
appEntity.isRecommend = false
AppDatabase.database.getAppDao().insertData(appEntity)
}
}
}
private fun checkSystemApp(context: Context, packageName: String): Boolean {
try {
val info = context.packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
if (info.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0) {
return true
}
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
}
return false
}
private fun removeDuplApp(list: List<AppEntity>): List<AppEntity> {
val hashMap: HashMap<String, AppEntity> = hashMapOf()
for (appEntity: AppEntity in list) {
if (!hashMap.containsKey(appEntity.packageName)) {
hashMap.put(appEntity.packageName, appEntity)
}
}
val appEntityList: MutableList<AppEntity> = mutableListOf()
for (entry in hashMap.entries) {
appEntityList.add(entry.value)
}
return appEntityList
}
public fun getAppList(context: Context, isUpdate: Boolean): List<AppEntity> {
val packageManager = context.packageManager
val intent = Intent(Intent.ACTION_MAIN, null)
intent.addCategory(Intent.CATEGORY_LAUNCHER)
val resolveInfos = packageManager.queryIntentActivities(intent, 0)
val systemAppList: MutableList<AppEntity> = mutableListOf()
val threeAppList: MutableList<AppEntity> = mutableListOf()
for (i in 0 until resolveInfos.size) {
val resolveInfo = resolveInfos[i]
val packageName = resolveInfo.activityInfo.packageName
if (Objects.equals(packageName, context.packageName)) {
continue
}
val appInfo: ApplicationInfo
try {
val applicationInfo =
packageManager.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES)
val appName = packageManager.getApplicationLabel(applicationInfo).toString()
val appEntity = AppEntity()
appEntity.packageName = packageName
appEntity.appName = appName
val isSystemApp = checkSystemApp(context, packageName)
if (isSystemApp) {
appEntity.isSyStem = true
systemAppList.add(appEntity)
} else {
appEntity.isSyStem = false
threeAppList.add(appEntity)
}
} catch (nameNotFoundException: PackageManager.NameNotFoundException) {
}
}
val uniqueSystemList: List<AppEntity> = removeDuplApp(systemAppList)
val uniqueThreeList: List<AppEntity> = removeDuplApp(threeAppList)
CoroutineScope(Dispatchers.IO).launch {
addDb(uniqueSystemList, true, isUpdate)
addDb(uniqueThreeList, false, isUpdate)
}
return uniqueThreeList
}
public fun delUnInstallApp(context: Context, packName: String): Boolean {
val packageManager = context.packageManager
return try {
packageManager.getApplicationInfo(packName, PackageManager.GET_UNINSTALLED_PACKAGES)
false
} catch (nameNotFoundException: PackageManager.NameNotFoundException) {
true
}
}
}

View File

@ -0,0 +1,16 @@
package com.kitobochi.softapp.timberlock.tools
import android.content.Context
import androidx.annotation.ColorRes
import androidx.annotation.DimenRes
import androidx.core.content.ContextCompat
class CustomViewTools {
fun getPx(context: Context, @DimenRes id: Int): Float {
return context.resources.getDimension(id)
}
fun getColor(context: Context?, @ColorRes id: Int): Int {
return ContextCompat.getColor(context!!, id)
}
}

View File

@ -0,0 +1,94 @@
package com.kitobochi.softapp.timberlock.tools
import android.content.Context
import android.graphics.PixelFormat
import android.graphics.Point
import android.os.Build
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import com.kitobochi.softapp.timberlock.App
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.ui.customview.InputStateView
import com.kitobochi.softapp.timberlock.ui.customview.KeyboardView
import com.kitobochi.softapp.timberlock.ui.customview.ListenerLock
import java.util.Objects
class LockManager(context: Context) {
private lateinit var mContext: Context
private lateinit var mView: View
private lateinit var lockView: KeyboardView
private lateinit var windowManager: WindowManager
private lateinit var layoutParams: WindowManager.LayoutParams
lateinit var lockManager: LockManager
init {
mContext = context
mView = LayoutInflater.from(context).inflate(R.layout.view_lock, null, false)
windowManager = mContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
initView()
val myState = mView.findViewById<InputStateView>(R.id.indicator_dots)
lockView = mView.findViewById(R.id.pin_lock_view)
lockView.attachIndicatorDots(myState)
lockView.setPinLockListener(object : ListenerLock {
override fun onInPutComplete(pin: String) {
val pwd = App().getPwd()
if (Objects.equals(pin, pin)) {
unLock()
} else {
lockView.resetPinLockView()
}
}
})
}
fun unLock() {
try {
windowManager.removeView(mView)
} catch (exception: Exception) {
}
}
fun showLockView() {
lockView.resetPinLockView()
windowManager.addView(mView, layoutParams)
}
private fun initView() {
var type = 0
type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_PHONE
}
val displayMetrics = DisplayMetrics()
windowManager.getDefaultDisplay().getMetrics(displayMetrics)
layoutParams = WindowManager.LayoutParams()
layoutParams.type = type
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
layoutParams.format = PixelFormat.RGBA_8888
layoutParams.flags =
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_FULLSCREEN or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
layoutParams.gravity = Gravity.START or Gravity.TOP
val screenSize = Point()
windowManager.getDefaultDisplay().getRealSize(screenSize)
layoutParams.width = screenSize.x
layoutParams.height = screenSize.y
}
}

View File

@ -0,0 +1,70 @@
package com.kitobochi.softapp.timberlock.tools
import android.app.Activity
import android.app.AppOpsManager
import android.app.usage.UsageEvents
import android.app.usage.UsageStatsManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Process
import android.provider.Settings
import android.text.TextUtils
import androidx.annotation.RequiresApi
class LockServiceManager {
fun checkUsageStats(context: Context): String {
val sUsageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val endTime = System.currentTimeMillis()
val beginTime = endTime - 10000
var result = ""
val event = UsageEvents.Event()
val usageEvents = sUsageStatsManager.queryEvents(beginTime, endTime)
while (usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event)
if (event.eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
result = event.packageName
}
}
return if (!TextUtils.isEmpty(result)) {
result
} else {
""
}
}
fun checkPermission(context: Context): Boolean {
val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
var mode = 0
mode = appOps.checkOpNoThrow("android:get_usage_stats", Process.myUid(), context.packageName)
return mode == AppOpsManager.MODE_ALLOWED
}
@RequiresApi(Build.VERSION_CODES.M)
fun getCanDrawOverlays(context: Context?): Boolean {
return Settings.canDrawOverlays(context)
}
fun toSetUsagePermission(context: Activity, requestCode: Int) {
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
// Uri uri = Uri.fromParts("package", context.getPackageName(), null);
// intent.setData(uri);
context.startActivityForResult(intent, requestCode)
}
fun goDrawOverlays(activity: Activity, requestCode: Int) {
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
//8.0
} else {
// 6.0、7.0、9.0
val uri = Uri.fromParts("package", activity.packageName, null)
intent.setData(uri)
// intent.setData(Uri.parse("package:" + activity.getPackageName()));
}
activity.startActivityForResult(intent, requestCode)
}
}

View File

@ -0,0 +1,35 @@
package com.kitobochi.softapp.timberlock.ui.activity
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
abstract class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(getActivityView())
initView()
}
open fun initView() {
initStatusBar()
}
abstract fun getActivityView(): View
private fun initStatusBar() {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// window.decorView.systemUiVisibility =
// (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE) or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
// window.statusBarColor = Color.TRANSPARENT
// }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.decorView.systemUiVisibility =
(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
window.statusBarColor = Color.TRANSPARENT
}
}
}

View File

@ -0,0 +1,195 @@
package com.kitobochi.softapp.timberlock.ui.activity
import android.content.Intent
import android.os.Build
import android.util.Log
import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.viewpager.widget.ViewPager
import com.google.android.material.tabs.TabLayout
import com.kitobochi.softapp.timberlock.App
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.databinding.ActivityMainBinding
import com.kitobochi.softapp.timberlock.databinding.ViewTabBinding
import com.kitobochi.softapp.timberlock.service.AppLockService
import com.kitobochi.softapp.timberlock.tools.LockServiceManager
import com.kitobochi.softapp.timberlock.ui.customview.DialogPer
import com.kitobochi.softapp.timberlock.ui.customview.onPermssionListener
import com.kitobochi.softapp.timberlock.ui.fragment.AppListFragment
import com.kitobochi.softapp.timberlock.ui.fragment.SettingFragment
class MainActivity : BaseActivity(), onPermssionListener {
private lateinit var binding: ActivityMainBinding
private lateinit var dialogPer: DialogPer
private var fragmentList: ArrayList<Fragment> = arrayListOf()
override fun getActivityView(): View {
binding = ActivityMainBinding.inflate(layoutInflater);
return binding.root
}
@RequiresApi(Build.VERSION_CODES.M)
override fun initView() {
super.initView()
initTabLayout()
initViewPager()
startPermission()
startService(Intent(this, AppLockService::class.java))
}
@RequiresApi(Build.VERSION_CODES.M)
private fun checkPermission(): Boolean {
val b: Boolean = LockServiceManager().checkPermission(this)
val canDrawOverlays: Boolean = LockServiceManager().getCanDrawOverlays(this)
return b && canDrawOverlays
}
@RequiresApi(Build.VERSION_CODES.M)
private fun startPermission() {
if (!checkPermission()) {
dialogPer = DialogPer.newInstance()
dialogPer.setListener(this)
dialogPer.show(supportFragmentManager, "")
}
}
private fun initViewPager() {
val titles = arrayOf<String>(
getString(R.string.text_system),
getString(R.string.text_third),
getString(R.string.text_setting)
)
binding.mainViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
binding.mainTab.getTabAt(position)?.select()
}
override fun onPageScrollStateChanged(state: Int) {
}
})
binding.mainViewPager.adapter = object : FragmentStatePagerAdapter(supportFragmentManager) {
override fun getCount(): Int {
return fragmentList.size
}
override fun getItem(position: Int): Fragment {
return fragmentList[position]
}
override fun getPageTitle(position: Int): CharSequence {
return titles[position]
}
}
}
private fun initTabLayout() {
fragmentList.add(AppListFragment(true))
fragmentList.add(AppListFragment(false))
fragmentList.add(SettingFragment())
val titles = arrayOf<String>(
getString(R.string.text_system),
getString(R.string.text_third),
getString(R.string.text_setting)
)
for (i in 0 until fragmentList.size) {
val newTab = binding.mainTab.newTab()
val viewTabBinding = ViewTabBinding.inflate(layoutInflater)
viewTabBinding.tvTabtext.text = titles[i]
newTab.customView = viewTabBinding.root
binding.mainTab.addTab(newTab)
}
val tabAt = binding.mainTab.getTabAt(1)
val tabAt2 = binding.mainTab.getTabAt(2)
if (tabAt != null && tabAt2 != null) {
updateTab(tabAt, false)
updateTab(tabAt2, false)
}
binding.mainTab.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(p0: TabLayout.Tab?) {
if (p0 != null) {
updateTab(p0, true)
binding.mainViewPager.setCurrentItem(p0.position)
}
}
override fun onTabUnselected(p0: TabLayout.Tab?) {
p0?.let { updateTab(it, false) }
}
override fun onTabReselected(p0: TabLayout.Tab?) {
}
})
}
private fun updateTab(tabAt: TabLayout.Tab, b: Boolean) {
val customView = tabAt.customView ?: return
val textView = customView.findViewById<TextView>(R.id.tv_tabtext)
textView.isSelected = b
if (b) {
textView.background = ContextCompat.getDrawable(this@MainActivity, R.drawable.shape_yellow_r30)
} else {
textView.background = null
}
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onToSetting() {
val b: Boolean = LockServiceManager().checkPermission(this)
val canDrawOverlays: Boolean = LockServiceManager().getCanDrawOverlays(this)
if (!b) {
LockServiceManager().toSetUsagePermission(this@MainActivity, App().reqCodeUsage)
} else {
if (!canDrawOverlays) {
LockServiceManager().goDrawOverlays(this, App().reqCodeOverlays)
}
}
}
@Deprecated("Deprecated in Java")
@RequiresApi(Build.VERSION_CODES.M)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == App().reqCodeUsage) {
if (checkPermission()) {
dialogPer.dismiss()
return
}
val canDrawOverlays = LockServiceManager().getCanDrawOverlays(this)
if (!canDrawOverlays) {
LockServiceManager().goDrawOverlays(this, App().reqCodeOverlays)
}
}
if (requestCode == App().reqCodeOverlays) {
if (checkPermission()) {
Log.d("---------","-------dismiss---")
dialogPer.dismiss()
} else {
Toast.makeText(this, getString(R.string.no_permission), Toast.LENGTH_SHORT).show()
}
}
}
}

View File

@ -0,0 +1,157 @@
package com.kitobochi.softapp.timberlock.ui.activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.CountDownTimer
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.applovin.mediation.MaxAd
import com.applovin.mediation.ads.MaxInterstitialAd
import com.kitobochi.softapp.timberlock.App
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.ad.AdListener
import com.kitobochi.softapp.timberlock.ad.AdManager
import com.kitobochi.softapp.timberlock.databinding.ActivitySetpwdBinding
class SetPwdActivity : BaseActivity(), View.OnClickListener {
private lateinit var binding: ActivitySetpwdBinding
private var isShowAd: Boolean = false
private val IS_SHOW_AD = "IS_SHOW_AD"
private val countTime: Long = 12000
private lateinit var adList: List<MaxInterstitialAd>
private lateinit var timer: CountDownTimer
override fun getActivityView(): View {
binding = ActivitySetpwdBinding.inflate(layoutInflater)
return binding.root
}
override fun initView() {
super.initView()
initAd()
initButton()
initInput()
}
private fun initAd() {
isShowAd = intent.getBooleanExtra(IS_SHOW_AD, false)
timer = object : CountDownTimer(countTime, 200) {
override fun onTick(millisUntilFinished: Long) {
if (isShowAd) {
startShowAd()
}
}
override fun onFinish() {
if (isShowAd) {
startShowAd()
}
}
}
startAd()
}
private fun startAd() {
if (!App.initOK) {
LocalBroadcastManager.getInstance(this).registerReceiver(object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
loadMyAdAndStart()
Log.d("------------", "------------1sucess")
}
}, IntentFilter(App.AD_INIT))
} else {
loadMyAdAndStart()
Log.d("------------", "------------2sucess")
}
}
private fun loadMyAdAndStart() {
adList = AdManager.adLoad()
timer.start()
}
private fun startShowAd() {
val checkCacheAd = AdManager.onCache(adList)
if (checkCacheAd == null) {
return
} else {
AdManager.setAdListener(checkCacheAd, object : AdListener {
override fun onFail(ad: MaxAd) {
}
override fun onSuccess() {
}
override fun onHidden() {
checkCacheAd.loadAd()
}
})
checkCacheAd.showAd()
}
}
private fun initInput() {
for (i in 0 until binding.layoutPwd.childCount) {
val editText = binding.layoutPwd.getChildAt(i) as EditText
var editNext: EditText? = null
if ((i + 1) < binding.layoutPwd.childCount) {
editNext = binding.layoutPwd.getChildAt(i + 1) as EditText
}
val finalEditText = editNext
editText.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
finalEditText?.requestFocus()
}
})
}
}
private fun initButton() {
binding.pwdBack.setOnClickListener(this)
binding.pwdOk.setOnClickListener(this)
}
override fun onClick(v: View?) {
when (v) {
binding.pwdOk -> {
val stringBuilder = StringBuilder()
stringBuilder.append(binding.et1.text.toString())
stringBuilder.append(binding.et2.text.toString())
stringBuilder.append(binding.et3.text.toString())
stringBuilder.append(binding.et4.text.toString())
if (stringBuilder.length == 4) {
App().updatePwd(stringBuilder.toString())
Toast.makeText(this@SetPwdActivity, getString(R.string.pwd_success), Toast.LENGTH_SHORT).show()
val intent = Intent(this@SetPwdActivity, MainActivity::class.java)
startActivity(intent)
} else {
Toast.makeText(this@SetPwdActivity, getString(R.string.pwd_err), Toast.LENGTH_SHORT).show()
}
}
binding.pwdBack -> {
finish()
}
}
}
}

View File

@ -0,0 +1,127 @@
package com.kitobochi.softapp.timberlock.ui.activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.CountDownTimer
import android.util.Log
import android.view.View
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.applovin.mediation.MaxAd
import com.applovin.mediation.ads.MaxInterstitialAd
import com.kitobochi.softapp.timberlock.App
import com.kitobochi.softapp.timberlock.ad.AdListener
import com.kitobochi.softapp.timberlock.ad.AdManager
import com.kitobochi.softapp.timberlock.databinding.ActivityStartBinding
import com.vungle.ads.Ad
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class StartPageActivity : BaseActivity() {
private lateinit var binding: ActivityStartBinding
// private val coroutineScope = CoroutineScope(Dispatchers.Main)
private val countTime: Long = 12000
private val IS_SHOW_AD = "IS_SHOW_AD"
private lateinit var adList: List<MaxInterstitialAd>
private lateinit var timer: CountDownTimer
private var needShow = true
override fun getActivityView(): View {
binding = ActivityStartBinding.inflate(layoutInflater)
return binding.root
}
override fun initView() {
super.initView()
Log.d("start-ad", "onCreate")
timer = object : CountDownTimer(countTime, 200) {
override fun onTick(millisUntilFinished: Long) {
if (needShow) {
startShowAd {}
}
}
override fun onFinish() {
if (needShow) {
startShowAd {
startMainActivity()
}
}
}
}
startAd()
// startMainActivity()
}
private fun startAd() {
if (!App.initOK) {
LocalBroadcastManager.getInstance(this).registerReceiver(object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
loadMyAdAndStart()
Log.d("------------", "------------1sucess")
}
}, IntentFilter(App.AD_INIT))
} else {
loadMyAdAndStart()
Log.d("------------", "------------2sucess")
}
}
private fun loadMyAdAndStart() {
adList = AdManager.adLoad()
timer.start()
}
private fun startShowAd(action: () -> Unit) {
val checkCacheAd = AdManager.onCache(adList)
if (checkCacheAd == null) {
action.invoke()
} else {
needShow = false
AdManager.setAdListener(checkCacheAd, object : AdListener {
override fun onFail(ad: MaxAd) {
startMainActivity()
}
override fun onSuccess() {
}
override fun onHidden() {
startMainActivity()
checkCacheAd.loadAd()
}
})
checkCacheAd.showAd()
}
}
private fun startMainActivity() {
if (App().getPwd().isEmpty()) {
val intent = Intent(this, SetPwdActivity::class.java)
intent.putExtra(IS_SHOW_AD, false)
startActivity(intent)
} else {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
finish()
}
override fun onDestroy() {
super.onDestroy()
timer.cancel()
}
}

View File

@ -0,0 +1,131 @@
package com.kitobochi.softapp.timberlock.ui.adapter
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.widget.SwitchCompat
import androidx.recyclerview.widget.RecyclerView
import com.applovin.mediation.MaxAd
import com.applovin.mediation.ads.MaxInterstitialAd
import com.kitobochi.softapp.timberlock.App
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.ad.AdListener
import com.kitobochi.softapp.timberlock.ad.AdManager
import com.kitobochi.softapp.timberlock.ad.AdMsgListener
import com.kitobochi.softapp.timberlock.db.AppDatabase
import com.kitobochi.softapp.timberlock.db.AppEntity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class AppListAdapter(
context: Context,
private val msgListener: AdMsgListener
) : RecyclerView.Adapter<AppListAdapter.AppListVH>() {
private val mContext: Context = context
private val packageManager = context.packageManager
private var list: List<AppEntity> = mutableListOf()
public fun updateSystemApp(infoList: List<AppEntity>) {
list = infoList
notifyDataSetChanged()
}
inner class AppListVH(view: View) : RecyclerView.ViewHolder(view) {
val imageView = itemView.findViewById<ImageView>(R.id.item_logo)
val textView = itemView.findViewById<TextView>(R.id.item_name)
val switchCompat = itemView.findViewById<SwitchCompat>(R.id.app_switch)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppListVH {
return AppListVH(LayoutInflater.from(parent.context).inflate(R.layout.item_app, parent, false))
}
override fun getItemCount(): Int {
return list.size
}
private fun getAppLog(packageName: String): Drawable {
val applicationInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES)
return packageManager.getApplicationIcon(applicationInfo)
}
override fun onBindViewHolder(holder: AppListVH, position: Int) {
holder.switchCompat.setOnCheckedChangeListener(null)
val appEntity = list[position]
val appName = appEntity.appName
val lock = appEntity.isLock
holder.switchCompat.isChecked = lock
holder.switchCompat.setOnCheckedChangeListener(
CompoundButton.OnCheckedChangeListener
{ _: CompoundButton, isChecked: Boolean ->
CoroutineScope(Dispatchers.IO).launch {
appEntity.isLock = isChecked
AppDatabase.database.getAppDao().updateData(dataApp = appEntity)
}
var format: String
if (isChecked) {
format = String.format(mContext.getString(R.string.text_locked), appName)
} else {
format = String.format(mContext.getString(R.string.text_unlocked), appName)
}
Toast.makeText(mContext, format, Toast.LENGTH_SHORT).show()
if (App.count % 5 == 0) {
showAd({ showPopup(format) }, format)
}
App.count++
})
try {
val appLog = getAppLog(appEntity.packageName)
holder.imageView.setImageDrawable(appLog)
} catch (e: PackageManager.NameNotFoundException) {
}
holder.textView.text = appName
}
private fun showAd(action: () -> Unit, msg: String) {
val adList = AdManager.adLoad()
val checkCacheAd = AdManager.onCache(adList)
if (checkCacheAd == null) {
action.invoke()
} else {
AdManager.setAdListener(checkCacheAd, object : AdListener {
override fun onFail(ad: MaxAd) {
showPopup(msg)
}
override fun onSuccess() {
}
override fun onHidden() {
showPopup(msg)
checkCacheAd.loadAd()
}
})
checkCacheAd.showAd()
}
}
private fun showPopup(msg: String) {
msgListener.msg(msg)
}
}

View File

@ -0,0 +1,154 @@
package com.kitobochi.softapp.timberlock.ui.adapter
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.recyclerview.widget.RecyclerView
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.ui.customview.CustomBundle
class KeyboardAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var mOnNumberListener: OnNumberClickListener? = null
private var mOnDeleteListener: OnDeleteClickListener? = null
private var mCustomBundle: CustomBundle? = null
private var mCurLength = 0
private val mKeyValues: IntArray
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val viewHolder: RecyclerView.ViewHolder
val inflater = LayoutInflater.from(parent.context)
if (viewType == TYPE_NUMBER) {
val view: View = inflater.inflate(R.layout.item_number, parent, false)
viewHolder = NumberViewHolder(view)
} else {
val view: View = inflater.inflate(R.layout.item_delete, parent, false)
viewHolder = DeleteViewHolder(view)
}
return viewHolder
}
init {
mKeyValues = getKeyValues(intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 0))
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder.itemViewType == TYPE_NUMBER) {
val vh1 = holder as NumberViewHolder
setNumberBtn(vh1, position)
}
}
private fun setNumberBtn(holder: NumberViewHolder?, position: Int) {
if (holder != null) {
if (position == 9) {
holder.mNumberButton.visibility = View.GONE
} else {
holder.mNumberButton.text = mKeyValues[position].toString()
holder.mNumberButton.visibility = View.VISIBLE
holder.mNumberButton.tag = mKeyValues[position]
}
if (mCustomBundle != null) {
holder.mNumberButton.setTextColor(mCustomBundle!!.textColor)
if (mCustomBundle!!.backgroundDrawable != null) {
holder.mNumberButton.background = mCustomBundle!!.backgroundDrawable
}
holder.mNumberButton.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
mCustomBundle!!.textSize.toFloat()
)
val params: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
mCustomBundle!!.buttonSize,
mCustomBundle!!.buttonSize
)
holder.mNumberButton.setLayoutParams(params)
}
}
}
override fun getItemCount(): Int {
return 12
}
override fun getItemViewType(position: Int): Int {
return if (position == itemCount - 1) {
VIEW_TYPE_DELETE
} else TYPE_NUMBER
}
fun setPinLength(pinLength: Int) {
mCurLength = pinLength
}
private fun getKeyValues(keyValues: IntArray): IntArray {
val adjustedKeyValues = IntArray(keyValues.size + 1)
for (i in keyValues.indices) {
if (i < 9) {
adjustedKeyValues[i] = keyValues[i]
} else {
adjustedKeyValues[i] = -1
adjustedKeyValues[i + 1] = keyValues[i]
}
}
return adjustedKeyValues
}
fun setOnItemClickListener(onNumberClickListener: OnNumberClickListener?) {
mOnNumberListener = onNumberClickListener
}
fun setOnDeleteClickListener(onDeleteClickListener: OnDeleteClickListener?) {
mOnDeleteListener = onDeleteClickListener
}
fun setCustomizationOptions(customBundle: CustomBundle?) {
mCustomBundle = customBundle
}
inner class NumberViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var mNumberButton: Button
init {
mNumberButton = itemView.findViewById<View>(R.id.deleteLayout) as Button
mNumberButton.setOnClickListener { v ->
if (mOnNumberListener != null) {
mOnNumberListener!!.onNumberClicked(v.tag as Int)
}
}
}
}
interface OnNumberClickListener {
fun onNumberClicked(keyValue: Int)
}
interface OnDeleteClickListener {
fun onDeleteClicked()
}
inner class DeleteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private var mDeleteLayout: LinearLayout
private var mDeleteImage: ImageView
init {
mDeleteLayout = itemView.findViewById<View>(R.id.deleteLayout) as LinearLayout
mDeleteImage = itemView.findViewById<View>(R.id.deleteImage) as ImageView
if (mCustomBundle?.isShowDeleteButton!! && mCurLength > 0) {
mDeleteLayout.setOnClickListener {
if (mOnDeleteListener != null) {
mOnDeleteListener!!.onDeleteClicked()
}
}
}
}
}
companion object {
private const val TYPE_NUMBER = 0
private const val VIEW_TYPE_DELETE = 1
}
}

View File

@ -0,0 +1,18 @@
package com.kitobochi.softapp.timberlock.ui.customview
import android.graphics.drawable.Drawable
class CustomBundle {
@JvmField
var textColor = 0
@JvmField
var textSize = 0
var isShowDeleteButton: Boolean = false
@JvmField
var buttonSize = 0
@JvmField
var backgroundDrawable: Drawable? = null
}

View File

@ -0,0 +1,44 @@
package com.kitobochi.softapp.timberlock.ui.customview
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.databinding.ViewDialogBinding
class DialogPer : DialogFragment() {
private lateinit var binding: ViewDialogBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = ViewDialogBinding.inflate(getLayoutInflater())
dialog!!.setCanceledOnTouchOutside(false)
dialog!!.setCancelable(false)
val window = dialog!!.window
window!!.setBackgroundDrawableResource(R.color.null_color)
window.decorView.setPadding(0, 0, 0, 0)
val wlp = window.attributes
wlp.gravity = Gravity.CENTER
wlp.width = WindowManager.LayoutParams.MATCH_PARENT
wlp.height = WindowManager.LayoutParams.WRAP_CONTENT
window.setAttributes(wlp)
binding.tvGo.setOnClickListener(View.OnClickListener { listener?.onToSetting() })
return binding.getRoot()
}
private var listener: onPermssionListener? = null
public fun setListener(listener: onPermssionListener?) {
this.listener = listener
}
companion object{
fun newInstance(): DialogPer {
return DialogPer()
}
}
}

View File

@ -0,0 +1,90 @@
package com.kitobochi.softapp.timberlock.ui.customview
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
import androidx.core.view.ViewCompat
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.tools.CustomViewTools
class InputStateView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
LinearLayout(context, attrs, defStyleAttr) {
private var mPinLength = 0
private var mPreviousLength = 0
private var mDotDiameter = 0
private var mDotSpacing = 0
private var mFillDrawable = 0
private var mEmptyDrawable = 0
private fun initView(context: Context) {
ViewCompat.setLayoutDirection(this, ViewCompat.LAYOUT_DIRECTION_LTR)
for (i in 0 until mPinLength) {
val dot = View(context)
emptyDot(dot)
val params = LayoutParams(
mDotDiameter,
mDotDiameter
)
params.setMargins(mDotSpacing, 0, mDotSpacing, 0)
dot.setLayoutParams(params)
addView(dot)
}
}
init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyLock)
try {
mDotDiameter = typedArray.getDimension(
R.styleable.MyLock_dotDiameter,
CustomViewTools().getPx(getContext(), R.dimen.default_dot_diameter)
).toInt()
mDotSpacing = typedArray.getDimension(
R.styleable.MyLock_dotSpacing,
CustomViewTools().getPx(getContext(), R.dimen.default_dot_spacing)
).toInt()
mFillDrawable = typedArray.getResourceId(
R.styleable.MyLock_dotFilledBackground,
R.drawable.shape_oval_white
)
mEmptyDrawable = typedArray.getResourceId(
R.styleable.MyLock_dotEmptyBackground,
R.drawable.shape_oval_gray
)
mPinLength = typedArray.getInt(R.styleable.MyLock_pinLength, DEFAULT_PIN_LENGTH)
} finally {
typedArray.recycle()
}
initView(context)
}
private fun emptyDot(dot: View) {
dot.setBackgroundResource(mEmptyDrawable)
dot.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start()
}
private fun fillDot(dot: View) {
dot.setBackgroundResource(mFillDrawable)
dot.animate().scaleX(1.2f).scaleY(1.2f).setDuration(100).start()
}
fun updateDot(length: Int) {
mPreviousLength = if (length > 0) {
if (length > mPreviousLength) {
fillDot(getChildAt(length - 1))
} else {
emptyDot(getChildAt(length))
}
length
} else {
for (i in 0 until childCount) {
val v = getChildAt(i)
emptyDot(v)
}
0
}
}
companion object {
private const val DEFAULT_PIN_LENGTH = 4
}
}

View File

@ -0,0 +1,178 @@
package com.kitobochi.softapp.timberlock.ui.customview
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.tools.CustomViewTools
import com.kitobochi.softapp.timberlock.ui.adapter.KeyboardAdapter
class KeyboardView : RecyclerView {
private var mPin = ""
var pinLength = 0
private set
private var mHorizontalSpacing = 0
private var mVerticalSpacing = 0
private var mTextColor = 0
private var mTextSize = 0
private var mButtonSize = 0
private var mButtonBgDraw: Drawable? = null
private var mAdapter: KeyboardAdapter? = null
private var mPinLockListener: ListenerLock? = null
private var mCustomBundle: CustomBundle? = null
var isShowDeleteButton = false
private set
private var mMyDots: InputStateView? = null
private val numberClickListener: KeyboardAdapter.OnNumberClickListener =
object : KeyboardAdapter.OnNumberClickListener {
override fun onNumberClicked(keyValue: Int) {
if (mPin.length < pinLength) {
mPin += keyValue.toString()
if (isIndicatorDotsAttached) {
mMyDots?.updateDot(mPin.length)
}
if (mPin.length == 1) {
mAdapter?.setPinLength(mPin.length)
mAdapter?.notifyItemChanged(mAdapter!!.itemCount - 1)
}
if (mPinLockListener != null) {
if (mPin.length == pinLength) {
mPinLockListener!!.onInPutComplete(mPin)
} else {
}
}
} else {
if (!isShowDeleteButton) {
resetPinLockView()
mPin += keyValue.toString()
if (isIndicatorDotsAttached) {
mMyDots?.updateDot(mPin.length)
}
if (mPinLockListener != null) {
// mPinLockListener.onPinChange(mPin.length(), mPin);
}
} else {
mPinLockListener?.onInPutComplete(mPin)
}
}
}
}
private val mOnDeleteClickListener: KeyboardAdapter.OnDeleteClickListener =
object : KeyboardAdapter.OnDeleteClickListener {
override fun onDeleteClicked() {
if (mPin.length > 0) {
mPin = mPin.substring(0, mPin.length - 1)
if (isIndicatorDotsAttached) {
mMyDots?.updateDot(mPin.length)
}
if (mPin.length == 0) {
mAdapter?.setPinLength(mPin.length)
mAdapter?.notifyItemChanged(mAdapter!!.itemCount - 1)
}
if (mPinLockListener != null) {
if (mPin.length == 0) {
// mPinLockListener.onEmpty();
clearInternalPin()
} else {
// mPinLockListener.onPinChange(mPin.length(), mPin);
}
}
} else {
if (mPinLockListener != null) {
}
}
}
}
constructor(context: Context?) : super(context!!) {
init(null, 0)
}
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs) {
init(attrs, 0)
}
constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context!!, attrs, defStyle) {
init(attrs, defStyle)
}
private fun init(attributeSet: AttributeSet?, defStyle: Int) {
val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.MyLock)
try {
pinLength = typedArray.getInt(R.styleable.MyLock_pinLength, DEFAULT_PWD_LENGTH)
mHorizontalSpacing = typedArray.getDimension(
R.styleable.MyLock_keypadHorizontalSpacing, CustomViewTools().getPx(
context, R.dimen.default_horizontal_spacing
)
).toInt()
mVerticalSpacing = typedArray.getDimension(
R.styleable.MyLock_keypadVerticalSpacing,
CustomViewTools().getPx(context, R.dimen.default_vertical_spacing)
).toInt()
mTextColor =
typedArray.getColor(
R.styleable.MyLock_keypadTextColor,
CustomViewTools().getColor(context, R.color.white)
)
mTextSize = typedArray.getDimension(
R.styleable.MyLock_keypadTextSize,
CustomViewTools().getPx(context, R.dimen.default_text_size)
).toInt()
mButtonSize = typedArray.getDimension(
R.styleable.MyLock_keypadButtonSize,
CustomViewTools().getPx(context, R.dimen.default_button_size)
).toInt()
mButtonBgDraw = typedArray.getDrawable(R.styleable.MyLock_keypadButtonBackgroundDrawable)
isShowDeleteButton = typedArray.getBoolean(R.styleable.MyLock_keypadShowDeleteButton, true)
} finally {
typedArray.recycle()
}
mCustomBundle = CustomBundle()
mCustomBundle!!.textColor = mTextColor
mCustomBundle!!.textSize = mTextSize
mCustomBundle!!.buttonSize = mButtonSize
mCustomBundle!!.backgroundDrawable = mButtonBgDraw
mCustomBundle!!.isShowDeleteButton = isShowDeleteButton
initView()
}
private fun initView() {
mAdapter = KeyboardAdapter()
setLayoutManager(GridLayoutManager(context, 3))
mAdapter!!.setOnItemClickListener(numberClickListener)
mAdapter!!.setOnDeleteClickListener(mOnDeleteClickListener)
mAdapter!!.setCustomizationOptions(mCustomBundle)
setAdapter(mAdapter)
addItemDecoration(LockSpace(mHorizontalSpacing, mVerticalSpacing, 3, false))
setOverScrollMode(OVER_SCROLL_NEVER)
}
fun setPinLockListener(pinLockListener: ListenerLock?) {
mPinLockListener = pinLockListener
}
private fun clearInternalPin() {
mPin = ""
}
fun resetPinLockView() {
clearInternalPin()
mAdapter?.setPinLength(mPin.length)
mAdapter?.notifyItemChanged(mAdapter!!.getItemCount() - 1)
mMyDots?.updateDot(mPin.length)
}
val isIndicatorDotsAttached: Boolean
get() = mMyDots != null
fun attachIndicatorDots(mMyDots: InputStateView?) {
this.mMyDots = mMyDots
}
companion object {
private const val DEFAULT_PWD_LENGTH = 4
}
}

View File

@ -0,0 +1,6 @@
package com.kitobochi.softapp.timberlock.ui.customview
interface ListenerLock {
fun onInPutComplete(pin: String)
}

View File

@ -0,0 +1,35 @@
package com.kitobochi.softapp.timberlock.ui.customview
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
class LockSpace(
private val HSpace: Int,
private val mVSpace: Int,
private val mSpanCount: Int,
private val mInclude: Boolean
) :
ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val position = parent.getChildAdapterPosition(view)
val column = position % mSpanCount
if (mInclude) {
outRect.left = HSpace - column * HSpace / mSpanCount
outRect.right = (column + 1) * HSpace / mSpanCount
if (position < mSpanCount) {
outRect.top = mVSpace
}
outRect.bottom = mVSpace
} else {
outRect.left = column * HSpace / mSpanCount
outRect.right = HSpace - (column + 1) * HSpace / mSpanCount
if (position >= mSpanCount) {
outRect.top = mVSpace
}
}
}
}

View File

@ -0,0 +1,5 @@
package com.kitobochi.softapp.timberlock.ui.customview
interface onPermssionListener {
fun onToSetting()
}

View File

@ -0,0 +1,58 @@
package com.kitobochi.softapp.timberlock.ui.fragment
import android.app.AlertDialog
import android.util.Log
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.kitobochi.softapp.timberlock.ad.AdListener
import com.kitobochi.softapp.timberlock.ad.AdMsgListener
import com.kitobochi.softapp.timberlock.databinding.FragmentApplistBinding
import com.kitobochi.softapp.timberlock.db.AppDatabase
import com.kitobochi.softapp.timberlock.ui.adapter.AppListAdapter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AppListFragment(
private val isSystem: Boolean
) : BaseFragment() {
private lateinit var binding: FragmentApplistBinding
override fun getFragmentView(): View {
binding = FragmentApplistBinding.inflate(layoutInflater)
return binding.root
}
override fun initView() {
super.initView()
initAppList()
}
private fun initAppList() {
val adapter = AppListAdapter(requireContext(), object : AdMsgListener {
override fun msg(msg: String) {
// Log.e("------", "回调成功")
val builder = AlertDialog.Builder(requireContext())
builder.setTitle("Successfully set")
builder.setMessage(msg)
builder.setPositiveButton("OK") { dialog, _ ->
dialog.dismiss()
}
val alertDialog = builder.create()
alertDialog.show()
}
})
binding.appList.adapter = adapter
binding.appList.layoutManager = LinearLayoutManager(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val data = AppDatabase.database.getAppDao().findByType(isSystem, false)
withContext(Dispatchers.Main) {
if (data != null) {
adapter.updateSystemApp(data)
}
}
}
}
}

View File

@ -0,0 +1,27 @@
package com.kitobochi.softapp.timberlock.ui.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
abstract class BaseFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return getFragmentView()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}
open fun initView() {
}
abstract fun getFragmentView(): View
}

View File

@ -0,0 +1,61 @@
package com.kitobochi.softapp.timberlock.ui.fragment
import android.content.Intent
import android.net.Uri
import android.view.View
import com.kitobochi.softapp.timberlock.App
import com.kitobochi.softapp.timberlock.R
import com.kitobochi.softapp.timberlock.databinding.FragmentSettingBinding
import com.kitobochi.softapp.timberlock.tools.LockServiceManager
import com.kitobochi.softapp.timberlock.ui.activity.SetPwdActivity
class SettingFragment : BaseFragment(), View.OnClickListener {
private val IS_SHOW_AD = "IS_SHOW_AD"
private lateinit var binding: FragmentSettingBinding
override fun getFragmentView(): View {
binding = FragmentSettingBinding.inflate(layoutInflater)
return binding.root
}
override fun initView() {
super.initView()
initButton()
}
private fun initButton() {
binding.settingRating.setOnClickListener(this)
binding.settingShare.setOnClickListener(this)
binding.settingPassword.setOnClickListener(this)
// binding.settingInit.setOnClickListener(this)
}
override fun onClick(v: View?) {
when (v) {
binding.settingRating -> {
val url = getString(R.string.setting_link) + (activity?.packageName ?: "")
val intent = Intent(Intent.ACTION_VIEW)
intent.setData(Uri.parse(url))
startActivity(intent)
}
binding.settingShare -> {
val url = getString(R.string.setting_link) + (activity?.packageName ?: "")
val intent = Intent(Intent.ACTION_SEND)
intent.setType("text/plain")
intent.putExtra(Intent.EXTRA_TEXT, url)
startActivity(intent)
}
binding.settingPassword -> {
val intent = Intent(requireContext(), SetPwdActivity::class.java)
intent.putExtra(IS_SHOW_AD, true)
startActivity(intent)
}
// binding.settingInit -> {
//// LockServiceManager().toSetUsagePermission(requireActivity(), App().reqCodeUsage)
// }
}
}
}

View File

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_yellow_switch" android:state_checked="true" />
<item android:drawable="@drawable/shape_white_switch" android:state_checked="false" />
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/white" android:state_selected="true" />
<item android:color="@color/black" android:state_selected="false" />
</selector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/yellow_color" />
</shape>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/white" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="30dp" />
<solid android:color="@color/pink_bg_color" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="15dp" />
<solid android:color="@color/white" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="36dp" />
<solid android:color="@color/yellow_color" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="12dp"/>
<solid android:color="@color/main_bg_color"/>
</shape>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/ash_color" />
<corners android:radius="100dp" />
<size
android:width="36dp"
android:height="22dp" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="30dp" />
<solid android:color="@color/yellow_color" />
</shape>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/main_bg" />
<corners android:radius="100dp" />
<size
android:width="36dp"
android:height="22dp" />
</shape>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M512,0C229.9,0 0,229.9 0,512s229.9,512 512,512 512,-229.9 512,-512S794.1,0 512,0zM512,916c-222.7,0 -404,-181.2 -404,-404S289.3,108 512,108s404,181.2 404,404 -181.2,404 -404,404z"
android:fillColor="@color/white"/>
<path
android:pathData="M586.2,364.5H426l13.8,-13.8c13.8,-13.8 13.8,-36.9 0,-50.7s-36.9,-13.8 -51.2,0L308.2,379.9c-13.8,13.8 -13.8,36.9 0,50.7l80.4,80.4c7.2,7.2 16.4,10.8 25.6,10.8 9.2,0 18.4,-3.6 25.6,-10.8 13.8,-13.8 13.8,-36.9 0,-50.7l-3.6,-3.6h150c37.4,0 67.6,36.9 67.6,82.4s-30.2,82.4 -67.6,82.4h-230.4c-25.6,0 -46.1,20.5 -46.1,46.1s20.5,46.1 46.1,46.1h230.9c88.6,0 160.3,-78.3 160.3,-175.1s-72.2,-174.1 -160.8,-174.1z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M303.9,277.3h491.8a42.7,42.7 0,0 1,42.7 42.7v384a42.7,42.7 0,0 1,-42.7 42.7L303.9,746.7a42.7,42.7 0,0 1,-33 -15.7l-157.1,-192a42.7,42.7 0,0 1,0 -54l157.1,-192A42.7,42.7 0,0 1,303.9 277.3zM521.2,466.8l-98.7,-98.7a9.8,9.8 0,0 0,-13.8 0l-31.4,31.4a9.8,9.8 0,0 0,0 13.8l98.7,98.7 -98.7,98.7a9.8,9.8 0,0 0,0 13.8l31.4,31.4c3.8,3.8 10,3.8 13.8,0l98.7,-98.7 98.7,98.7c3.8,3.8 10,3.8 13.8,0l31.4,-31.4a9.8,9.8 0,0 0,0 -13.8l-98.7,-98.7 98.7,-98.7a9.8,9.8 0,0 0,0 -13.8l-31.4,-31.4a9.8,9.8 0,0 0,-13.8 0l-98.7,98.7z"
android:fillColor="#ffffff"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="@color/black"
android:pathData="M724.5,877.3c-7.8,0 -15.5,-2.9 -21.5,-8.3L575.8,753.4l-167.4,39.2c-11.9,2.7 -24.3,-1.4 -32,-10.8 -7.8,-9.4 -9.5,-22.4 -4.5,-33.5l70.7,-156.7 -89,-147c-6.3,-10.4 -6.2,-23.5 0.4,-33.8 6.5,-10.3 18.3,-16 30.5,-14.6L555.4,415l112.3,-130.1c8,-9.2 20.4,-13.2 32.3,-10 11.8,3 20.8,12.5 23.3,24.5l35,168.3 158.5,66.7c11.2,4.8 18.8,15.4 19.5,27.6 0.7,12.2 -5.5,23.7 -16.1,29.7l-149.3,85.2L756.4,848c-1,12.2 -8.8,22.7 -20.2,27.1 -3.7,1.5 -7.7,2.2 -11.7,2.2zM584.9,686.4c7.9,0 15.6,2.9 21.5,8.3l91.7,83.3 10.4,-123.5c0.9,-10.5 6.9,-19.9 16,-25.1L832.1,568l-114.2,-48c-9.7,-4.1 -16.8,-12.7 -18.9,-23l-25.2,-121.3 -81,93.8c-6.9,8 -17.3,11.9 -27.7,10.9L442,466.8l64.2,106c5.5,9 6.1,20.1 1.8,29.8l-51,112.9 120.6,-28.3c2.4,-0.5 4.9,-0.8 7.3,-0.8z"/>
<path
android:pathData="M637.4,268.8c-5.5,-10.7 -16.6,-17.9 -28.6,-17.9l-142.9,-0.9 -80.6,-118.2c-6.8,-9.8 -18.8,-15.4 -30.7,-13.7 -12.4,1.7 -22.2,10.2 -26,21.8l-44.8,135.7 -137.4,39.7c-11.9,3.4 -20.5,13.2 -22.6,25.2 -2.1,11.9 2.6,24.3 12.4,31.6l115.2,84.5 -4.4,142.9c-0.4,12.4 6,23.5 16.6,29.4 4.7,2.6 10.2,3.8 15.4,3.8 6.4,0 12.8,-2.1 18.3,-6.4l98.6,-70.4 -33.3,-55 -49.9,35.8 3,-94.7c0.4,-10.7 -4.3,-20.9 -12.8,-26.9l-76.4,-56.3 90.9,-26.5c10.2,-3 18.3,-10.7 21.3,-20.9l30.3,-90 53.3,78.5c6,9 15.8,14.1 26,14.1l95.1,0.4 -55.9,71.7 74.9,8.1 71.1,-91.7c4.7,-5.1 6.8,-12.4 6.8,-18.8 0.1,-5.1 -0.7,-10.2 -2.9,-14.9z"
android:fillColor="#FFCE00"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M365.7,438.9v-73.1a146.3,146.3 0,1 1,292.6 0v73.1h36.6a36.6,36.6 0,0 1,36.6 36.6v219.4a36.6,36.6 0,0 1,-36.6 36.6L329.1,731.4a36.6,36.6 0,0 1,-36.6 -36.6v-219.4a36.6,36.6 0,0 1,36.6 -36.6h36.6zM438.9,438.9h146.3v-73.1a73.1,73.1 0,0 0,-146.3 0v73.1zM365.7,512v146.3h292.6v-146.3h-292.6zM768.8,251.6A364.5,364.5 0,0 0,512 146.3C310,146.3 146.3,310 146.3,512s163.7,365.7 365.7,365.7 365.7,-163.7 365.7,-365.7h73.1c0,242.4 -196.5,438.9 -438.9,438.9S73.1,754.4 73.1,512 269.6,73.1 512,73.1c120.3,0 229.3,48.4 308.5,126.8l49,-49 25.9,181 -181,-25.9 54.4,-54.4z"
android:fillColor="@color/black"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M882.2,620.9l-24.1,-14c-11.6,-6.8 -18.1,-19.8 -16.3,-33.3 2.2,-15.1 3.3,-30.4 3.3,-46.2 0,-15.8 -1.2,-31.1 -3.3,-46.2 -1.8,-13.5 4.5,-26.4 19.5,-35.1l21,-12.1c14,-8 20.1,-24.8 14.8,-39.9 -7.2,-20.6 -16.3,-40.4 -26.8,-59.4 -2.5,-4.7 -5.3,-9.5 -8.2,-14.1 -11.1,-18.5 -23.8,-35.9 -37.8,-52.2 -10.5,-12.3 -28.1,-15.1 -45.1,-5.3l-21.3,12.3c-11.6,6.8 -26.3,5.8 -36.9,-2.5 -24.1,-19.1 -50.9,-34.8 -80,-46.4 -12.5,-5 -20.5,-17.3 -20.5,-30.6v-28.1c0,-16.1 -11.5,-29.9 -27.3,-32.9 -23.6,-4.3 -47.7,-6.5 -72.5,-6.5 -24.8,0 -48.9,2.2 -72.5,6.5 -15.8,3 -27.3,16.8 -27.3,32.9v28.1c0,13.3 -8,25.6 -20.5,30.6 -29.1,11.6 -55.9,27.3 -80,46.4 -10.6,8.3 -25.3,9.3 -36.9,2.5l-24.3,-14.1c-14,-8 -31.6,-5.2 -42.1,7.2 -14,16.3 -26.6,33.8 -37.8,52.2 -2.8,4.7 -5.7,9.5 -8.2,14.1 -10.5,19 -19.6,38.8 -26.8,59.4 -5.3,15.1 0.8,31.9 14.8,39.9l24.1,14c11.6,6.8 18.1,19.8 16.3,33.3 -2.2,15.1 -3.3,30.4 -3.3,46.2 0,15.8 1.2,31.1 3.3,46.2 1.8,13.5 -4.7,26.4 -16.3,33.3l-24.1,14c-14,8 -20.1,24.8 -14.8,39.9 7.2,20.6 16.3,40.4 26.8,59.4 2.5,4.7 5.3,9.5 8.2,14.1 11.1,18.5 23.8,35.9 37.8,52.2 10.5,12.3 28.1,15.1 42.1,7.2l24.3,-14.1c11.6,-6.8 26.3,-5.8 36.9,2.5 24.1,19.1 50.9,34.8 80,46.4 12.5,5 20.5,17.3 20.5,30.6v28.1c0,16.1 11.5,29.9 27.3,32.9 23.6,4.3 47.7,6.5 72.5,6.5 24.8,0 48.9,-2.2 72.5,-6.5 15.8,-3 27.3,-16.8 27.3,-32.9v-28.1c0,-13.3 8,-25.6 20.5,-30.6 29.1,-11.6 55.9,-27.3 80,-46.4 10.6,-8.3 25.3,-9.3 36.9,-2.5l24.3,14.1c14,8 31.6,5.2 42.1,-7.2 14,-16.3 26.6,-33.8 37.8,-52.2 2.8,-4.7 5.7,-9.5 8.2,-14.1 10.5,-19 19.6,-38.8 26.8,-59.4 5.2,-15.3 -0.9,-32.1 -14.9,-40.1zM520.7,677.1c-82.7,0 -149.7,-67 -149.7,-149.7 0,-82.7 67,-149.7 149.7,-149.7s149.7,67 149.7,149.7c0,82.7 -67,149.7 -149.7,149.7z"
android:fillColor="#2c2c2c"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="@color/black"
android:pathData="M558.9,699.7l-170.7,-93.9c-25.6,21.3 -55.5,34.1 -89.6,34.1 -72.5,0 -128,-55.5 -128,-128s55.5,-128 128,-128c38.4,0 68.3,17.1 93.9,38.4L597.3,320L597.3,298.7c0,-72.5 55.5,-128 128,-128s128,55.5 128,128 -55.5,128 -128,128c-34.1,0 -64,-12.8 -85.3,-34.1l-213.3,110.9v21.3l174.9,98.1c21.3,-17.1 51.2,-29.9 81.1,-29.9 72.5,0 128,55.5 128,128s-55.5,128 -128,128 -128,-55.5 -128,-128c0,-4.3 0,-12.8 4.3,-21.3zM298.7,554.7c25.6,0 42.7,-17.1 42.7,-42.7s-17.1,-42.7 -42.7,-42.7 -42.7,17.1 -42.7,42.7 17.1,42.7 42.7,42.7zM725.3,341.3c25.6,0 42.7,-17.1 42.7,-42.7s-17.1,-42.7 -42.7,-42.7 -42.7,17.1 -42.7,42.7 17.1,42.7 42.7,42.7zM682.7,768c25.6,0 42.7,-17.1 42.7,-42.7s-17.1,-42.7 -42.7,-42.7 -42.7,17.1 -42.7,42.7 17.1,42.7 42.7,42.7z" />
</vector>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp">
<shape android:shape="rectangle">
<solid android:color="@color/white" />
<size
android:width="18dp"
android:height="18dp" />
<corners android:radius="8dp" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp">
<shape android:shape="oval">
<solid android:color="@color/white" />
<size
android:width="18dp"
android:height="18dp" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/main_bg_color"
android:orientation="vertical"
tools:context=".ui.activity.MainActivity">
<TextView
android:id="@+id/main_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginStart="25dp"
android:layout_marginTop="45dp"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/main_title"
android:orientation="vertical">
<androidx.viewpager.widget.ViewPager
android:id="@+id/main_viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="14dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="12dp"
android:layout_weight="1"
android:background="@drawable/shape_pink_r30" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/main_tab"
android:layout_width="match_parent"
android:layout_height="54dp"
android:layout_marginStart="14dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="20dp"
android:background="@drawable/shape_pink_r30"
app:tabGravity="fill"
app:tabIndicatorHeight="0dp"
app:tabMaxWidth="0dp"
app:tabMode="fixed"
app:tabPaddingBottom="0dp"
app:tabPaddingEnd="0dp"
app:tabPaddingStart="0dp"
app:tabPaddingTop="0dp" />
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/main_bg_color"
tools:context="com.kitobochi.softapp.timberlock.ui.activity.SetPwdActivity">
<ImageView
android:id="@+id/pwd_back"
android:layout_width="34dp"
android:layout_height="34dp"
android:layout_marginStart="30dp"
android:layout_marginTop="48dp"
android:src="@drawable/svg_back" />
<ImageView
android:id="@+id/pwd_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="133dp"
android:src="@mipmap/icon_logo" />
<TextView
android:id="@+id/pwd_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/pwd_logo"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="@string/pwd_title"
android:textColor="@color/white"
android:textSize="28sp" />
<TextView
android:id="@+id/pwd_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/pwd_title"
android:layout_alignStart="@id/pwd_title"
android:layout_alignEnd="@id/pwd_title"
android:layout_centerHorizontal="true"
android:layout_marginTop="22dp"
android:gravity="center"
android:text="@string/pwd_content"
android:textColor="@color/white"
android:textSize="16sp" />
<LinearLayout
android:id="@+id/layout_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/pwd_sub"
android:layout_marginTop="60dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<EditText
android:id="@+id/et1"
android:layout_width="58dp"
android:layout_height="58dp"
android:background="@drawable/shape_pwd_bg"
android:gravity="center"
android:imeOptions="actionNext"
android:inputType="number"
android:maxLength="1"
android:text=""
android:textColor="@color/black"
android:textSize="23sp" />
<EditText
android:id="@+id/et2"
android:layout_width="58dp"
android:layout_height="58dp"
android:layout_marginStart="20dp"
android:background="@drawable/shape_pwd_bg"
android:gravity="center"
android:imeOptions="actionNext"
android:inputType="number"
android:maxLength="1"
android:textColor="@color/black"
android:textSize="23sp" />
<EditText
android:id="@+id/et3"
android:layout_width="58dp"
android:layout_height="58dp"
android:layout_marginStart="20dp"
android:background="@drawable/shape_pwd_bg"
android:gravity="center"
android:imeOptions="actionNext"
android:inputType="number"
android:maxLength="1"
android:textColor="@color/black"
android:textSize="23sp" />
<EditText
android:id="@+id/et4"
android:layout_width="58dp"
android:layout_height="58dp"
android:layout_marginStart="20dp"
android:background="@drawable/shape_pwd_bg"
android:gravity="center"
android:imeOptions="actionDone"
android:inputType="number"
android:maxLength="1"
android:textColor="@color/black"
android:textSize="23sp" />
</LinearLayout>
<TextView
android:id="@+id/pwd_ok"
android:layout_width="match_parent"
android:layout_height="63dp"
android:layout_below="@id/layout_pwd"
android:layout_marginStart="30dp"
android:layout_marginTop="80dp"
android:layout_marginEnd="30dp"
android:background="@drawable/shape_pwd_ok"
android:gravity="center"
android:text="@string/pwd_ok"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".ui.activity.StartPageActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="80dp"
android:layout_height="80dp"
app:cardCornerRadius="12dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/icon_logo" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="260dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginBottom="60dp"
android:gravity="center"
android:lineSpacingExtra="20dp"
android:lineSpacingMultiplier="0.6"
android:text="@string/app_name"
android:textColor="@color/main_bg_color"
android:textSize="26sp"
android:textStyle="bold" />
</LinearLayout>
<ProgressBar
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="110dp"
android:indeterminateTint="@color/main_bg_color"
android:visibility="visible" />
</FrameLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragment.AppListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/app_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="10dp" />
</FrameLayout>

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".ui.fragment.SettingFragment">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginStart="28dp"
android:layout_marginTop="28dp"
android:layout_marginEnd="28dp"
android:backgroundTint="@color/white"
app:cardCornerRadius="30dp">
<LinearLayout
android:id="@+id/setting_rating"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="27dp"
android:layout_height="27dp"
android:layout_marginStart="25dp"
android:src="@drawable/svg_rating" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:gravity="center"
android:text="@string/setting_rating"
android:textColor="@color/black"
android:textSize="14sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginStart="28dp"
android:layout_marginTop="18dp"
android:layout_marginEnd="28dp"
android:backgroundTint="@color/white"
app:cardCornerRadius="30dp">
<LinearLayout
android:id="@+id/setting_share"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="27dp"
android:layout_height="27dp"
android:layout_marginStart="25dp"
android:src="@drawable/svg_share" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:gravity="center"
android:text="@string/setting_share"
android:textColor="@color/black"
android:textSize="14sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginStart="28dp"
android:layout_marginTop="18dp"
android:layout_marginEnd="28dp"
android:backgroundTint="@color/white"
app:cardCornerRadius="30dp">
<LinearLayout
android:id="@+id/setting_password"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="27dp"
android:layout_height="27dp"
android:layout_marginStart="25dp"
android:src="@drawable/svg_reset_password" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:gravity="center"
android:text="@string/setting_password"
android:textColor="@color/black"
android:textSize="14sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="17dp"
android:paddingStart="26dp"
android:paddingEnd="26dp">
<ImageView
android:id="@+id/item_logo"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/item_logo"
android:layout_alignBottom="@id/item_logo"
android:layout_marginStart="12dp"
android:layout_toEndOf="@id/item_logo"
android:gravity="center"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="12sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/app_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:checked="true"
android:thumb="@drawable/thumb_sw"
app:track="@drawable/selector_switch" />
</RelativeLayout>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/deleteLayout"
android:layout_width="64dp"
android:layout_height="64dp"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/deleteImage"
android:layout_width="45dp"
android:layout_height="45dp"
android:adjustViewBounds="true"
android:clickable="false"
android:focusable="false"
android:scaleType="fitCenter"
android:src="@drawable/svg_delete" />
</LinearLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<Button
android:id="@+id/deleteLayout"
android:layout_width="64dp"
android:layout_height="64dp"
android:background="?android:attr/selectableItemBackground" />
</LinearLayout>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="26dp"
android:layout_marginEnd="26dp"
android:background="@drawable/shape_rect_r12"
android:paddingBottom="12dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="@string/dialog_title"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_sub"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:layout_below="@id/tv_title"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:lineSpacingExtra="10dp"
android:text="@string/dialog_content"
android:textColor="@color/white"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_go"
android:layout_width="match_parent"
android:layout_height="43dp"
android:layout_below="@id/tv_sub"
android:layout_marginStart="30dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="30dp"
android:background="@drawable/shape_yellow_r30"
android:gravity="center"
android:text="@string/dialog_go"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout>
</FrameLayout>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/main_bg_color"
android:orientation="vertical">
<ImageView
android:layout_width="85dp"
android:layout_height="85dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="140dp"
android:src="@mipmap/icon_logo" />
<TextView
android:id="@+id/tv_password_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="14dp"
android:layout_marginBottom="36dp"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="16sp" />
<com.kitobochi.softapp.timberlock.ui.customview.InputStateView
android:id="@+id/indicator_dots"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="22dp"
android:gravity="center_vertical"
app:dotDiameter="12dp"
app:dotSpacing="20dp"
app:indicatorType="fixed" />
<com.kitobochi.softapp.timberlock.ui.customview.KeyboardView
android:id="@+id/pin_lock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="28dp"
app:keypadHorizontalSpacing="64dp"
app:keypadShowDeleteButton="true"
app:keypadTextColor="@color/white"
app:keypadTextSize="36sp"
app:keypadVerticalSpacing="24dp"
app:pinLength="4" />
</LinearLayout>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="4dp"
android:paddingEnd="4dp">
<TextView
android:id="@+id/tv_tabtext"
android:layout_width="match_parent"
android:layout_height="38dp"
android:background="@drawable/shape_yellow_r30"
android:gravity="center"
android:text="@string/app_name"
android:textColor="@drawable/selector_text_color"
android:textSize="14sp" />
</FrameLayout>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,7 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.TimberLock" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style>
</resources>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Lock_Theme">
<attr name="app_bar_bg" format="reference|color" />
<attr name="act_bg" format="reference|color" />
<attr name="menu_bg" format="reference|color" />
<attr name="image_color" format="reference|color" />
<attr name="image_color_2" format="reference|color" />
<attr name="warning" format="reference|color" />
<attr name="lock_bg" format="reference|color" />
<attr name="lock_keypad_button_color" format="reference|color" />
<attr name="lock_keypad_button_bg_color" format="reference|color" />
<attr name="btn_pressed_shadow" format="reference|color" />
<attr name="text_1" format="reference|color" />
<attr name="text_2" format="reference|color" />
<attr name="text_3" format="reference|color" />
<attr name="sc_track_color" format="reference|color" />
</declare-styleable>
<declare-styleable name="MyLock">
<attr name="pinLength" format="integer" />
<attr name="keypadShowDeleteButton" format="boolean" />
<attr name="dotEmptyBackground" format="reference" />
<attr name="dotFilledBackground" format="reference" />
<attr name="dotDiameter" format="dimension" />
<attr name="dotSpacing" format="dimension" />
<attr name="indicatorType" format="enum">
<enum name="fixed" value="0" />
<enum name="fill" value="1" />
<enum name="fillWithAnimation" value="2" />
</attr>
<attr name="keypadTextColor" format="color" />
<attr name="keypadTextSize" format="dimension" />
<attr name="keypadButtonSize" format="dimension" />
<attr name="keypadVerticalSpacing" format="dimension" />
<attr name="keypadHorizontalSpacing" format="dimension" />
<attr name="keypadButtonBackgroundDrawable" format="integer" />
<attr name="keypadDeleteButtonDrawable" format="integer" />
</declare-styleable>
</resources>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF2C2C2C</color>
<color name="white">#FFFFFFFF</color>
<color name="yellow_color">#FFFF9800</color>
<color name="blue_bg_color">#80BFEFFF</color>
<color name="pink_bg_color">#FFFFE4E1</color>
<color name="main_bg_color">#FF8E8EFE</color>
<color name="white_sw_color">#E5E5E5</color>
<color name="null_color">#00000000</color>
<color name="main_bg">#FF9800</color>
<color name="ash_color">#ffaaa8a8</color>
</resources>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="default_text_size">16sp</dimen>
<dimen name="default_button_size">60dp</dimen>
<dimen name="default_horizontal_spacing">32dp</dimen>
<dimen name="default_vertical_spacing">0dp</dimen>
<dimen name="default_dot_diameter">8dp</dimen>
<dimen name="default_dot_spacing">8dp</dimen>
</resources>

View File

@ -0,0 +1,27 @@
<resources>
<string name="app_name">AppLock Defender</string>
<string name="text_system">System App</string>
<string name="text_third">Third-party App</string>
<string name="text_setting">Setting</string>
<string name="setting_system">System Setting</string>
<string name="setting_rating">Rating this application</string>
<string name="setting_share">Share this application</string>
<string name="setting_password">Reset password</string>
<string name="setting_link">https://play.google.com/store/apps/details?id=</string>
<string name="text_locked">locked: %s</string>
<string name="text_unlocked">Unlocked: %s</string>
<string name="pwd_title">Set lock password</string>
<string name="pwd_content">Set your application lock password so that you can lock the application when you open it</string>
<string name="pwd_ok">OK</string>
<string name="pwd_success">Have successfully set the password</string>
<string name="pwd_err">Please input complete</string>
<string name="dialog_title">Please grant permissions for normal use applications</string>
<string name="dialog_content">1.Usage access\n2.Display on top of other apps</string>
<string name="dialog_go">GO</string>
<string name="no_permission">For normal use, please grant relevant permissions</string>
</resources>

View File

@ -0,0 +1,9 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.TimberLock" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
<style name="Theme.TimberLock" parent="Base.Theme.TimberLock" />
</resources>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

View File

@ -0,0 +1,17 @@
package com.kitobochi.softapp.timberlock
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

14
build.gradle Normal file
View File

@ -0,0 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript{
dependencies{
classpath("com.applovin.quality:AppLovinQualityServiceGradlePlugin:+")
}
}
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
id("com.google.gms.google-services") version "4.3.15" apply false
id ("com.google.firebase.crashlytics") version "2.9.2" apply false
}

26
gradle/libs.versions.toml Normal file
View File

@ -0,0 +1,26 @@
[versions]
agp = "8.1.3"
kotlin = "1.9.0"
coreKtx = "1.13.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
appcompat = "1.6.1"
material = "1.12.0"
activity = "1.8.0"
constraintlayout = "2.1.4"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Mon May 20 11:31:32 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

26
settings.gradle Normal file
View File

@ -0,0 +1,26 @@
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
maven { url "https://artifacts.applovin.com/android"}
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url "https://artifact.bytedance.com/repository/pangle" }
maven { url = uri("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea") }
}
}
rootProject.name = "TimberLock"
include ':app'