diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.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 diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..80bddb0 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..0897082 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..fdf8d99 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..8978d23 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..f570cae --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,58 @@ +import java.util.Date +import java.text.SimpleDateFormat + +val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date()) +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") +} + +android { + namespace = "com.tool.app.protectorpro" + compileSdk = 34 + + defaultConfig { + applicationId = "com.tool.app.protectorpro" + minSdk = 23 + targetSdk = 34 + versionCode = 1 + versionName = "1.0.0" + // setProperty("archivesBaseName", "AppLocker_V" + versionName + "(${versionCode})_$timestamp") + testInstrumentationRunner = "androidx.protectorpro.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = 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("de.hdodenhof:circleimageview:3.1.0") + + implementation("androidx.core:core-ktx:1.9.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.11.0") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.room:room-ktx:2.6.1") + implementation("androidx.room:room-runtime:2.6.1") + kapt("androidx.room:room-compiler:2.6.1") + + +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..9aeff70 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,33 @@ +# 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 + -keepclassmembers class com.tool.app.protectorpro.MyApplication{ + public static final java.lang.String DB_Name; + public static final int DB_Version; + } + -keepclassmembers class *{ + @androidx.room.Query ; + } + + -keep class com.tool.app.protectorpro.mydb.MyDataBase { *; } + -keep class com.tool.app.protectorpro.listener.ListenerDao { *; } + -keep class com.tool.app.protectorpro.mydb.DataApp { *; } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..061c1cf --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/tool/app/protectorpro/MyApplication.java b/app/src/main/java/com/tool/app/protectorpro/MyApplication.java new file mode 100644 index 0000000..3854f89 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/MyApplication.java @@ -0,0 +1,75 @@ +package com.tool.app.protectorpro; + +import android.app.Application; +import android.content.Context; +import android.content.SharedPreferences; + +import com.tool.app.protectorpro.mydb.DataApp; +import com.tool.app.protectorpro.mydb.MyDataBase; +import com.tool.app.protectorpro.tools.Common; +import com.tool.app.protectorpro.tools.MyThread; + +public class MyApplication extends Application { + public static String spName = "share_name"; + + public static MyApplication appContext; + + public static final int reqCodeUsage = 1; + public static final int DB_Version = 1; + public static final String Table_Name = "DataApp"; + public static final int reqCodeOverlays = 2; + public static final String DB_Name = "app_locker"; + + + public static SharedPreferences sp; + public static final String PWD_KEY = "locker_pwd"; + + public static SharedPreferences.Editor SpEditor; + public static final int type_0 = 0; + + public static final int type_1 = 1; + + public static final int type_2 = 2; + public static final String init_pwd_key = "pwd_type"; + + + @Override + public void onCreate() { + super.onCreate(); + appContext = this; + initSp(); + MyThread.runIO(() -> { + for (DataApp dataApp : MyDataBase.getInstance().getRoomDao().findApp()) { + Boolean needDelete = Common.delUnInstallApp(this, dataApp.getPackageName()); + if (needDelete) { + MyDataBase.getInstance().getRoomDao().deleteData(dataApp); + + } + } + }); + String pwd = getPwd(); + if (pwd.isEmpty()) { + Common.getAppList(this, false); + } else { + Common.getAppList(this, true); + } + + + } + + public static void updatePwd(String pwd) { + SpEditor.putString(PWD_KEY, pwd); + SpEditor.apply(); + } + + public static String getPwd() { + return sp.getString(PWD_KEY, ""); + } + + private void initSp() { + sp = MyApplication.appContext.getSharedPreferences(spName, Context.MODE_PRIVATE); + SpEditor = sp.edit(); + } + + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/activity/ActivityComplete.kt b/app/src/main/java/com/tool/app/protectorpro/activity/ActivityComplete.kt new file mode 100644 index 0000000..ad8bfd5 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/activity/ActivityComplete.kt @@ -0,0 +1,26 @@ +package com.tool.app.protectorpro.activity + +import android.annotation.SuppressLint +import android.graphics.Color +import android.os.Bundle +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import com.tool.app.protectorpro.R + +class ActivityComplete : AppCompatActivity() { + @SuppressLint("MissingInflatedId") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_complete) + findViewById(R.id.im_back).setOnClickListener { finish() } + initStatusBar() + } + + private fun initStatusBar() { + val decorView = window.decorView + val flag = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + or View.SYSTEM_UI_FLAG_LAYOUT_STABLE) + decorView.systemUiVisibility = flag + window.statusBarColor = Color.TRANSPARENT + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tool/app/protectorpro/activity/ActivityMain.java b/app/src/main/java/com/tool/app/protectorpro/activity/ActivityMain.java new file mode 100644 index 0000000..2820076 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/activity/ActivityMain.java @@ -0,0 +1,272 @@ +package com.tool.app.protectorpro.activity; + +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.SearchView; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.bottomsheet.BottomSheetDialog; +import com.google.android.material.tabs.TabLayout; +import com.tool.app.protectorpro.MyApplication; + +import com.tool.app.protectorpro.R; +import com.tool.app.protectorpro.databinding.ActivityMainLayoutBinding; +import com.tool.app.protectorpro.databinding.TabViewBinding; +import com.tool.app.protectorpro.listener.onPermssionListener; +import com.tool.app.protectorpro.service.LockService; +import com.tool.app.protectorpro.tools.Common; + +import java.util.ArrayList; +import java.util.List; + +public class ActivityMain extends AppCompatActivity implements SearchView.OnQueryTextListener, onPermssionListener { + private ActivityMainLayoutBinding binding; + + private DialogPer dialogPer; + + List fragmentList = new ArrayList<>(); + + private void initStatusBar() { + View decorView = getWindow().getDecorView(); + int flag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; + decorView.setSystemUiVisibility(flag); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityMainLayoutBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + binding.searchItem.setOnQueryTextListener(this); + initStatusBar(); + openPermission(); + startService(new Intent(this, LockService.class)); + initTab(); + initClick(); + } + + private void initTab() { + + String[] titles = new String[]{getString(R.string.text_system), getString(R.string.text_third), getString(R.string.text_recommended)}; + Drawable[] tabIcon = new Drawable[]{getDrawable(R.drawable.bg_tab_sys), getDrawable(R.drawable.bg_tab_three), getDrawable(R.drawable.bg_tab_lock)}; + + fragmentList.add(FragmentMy.newInstance(1)); + fragmentList.add(FragmentMy.newInstance(2)); + fragmentList.add(FragmentMy.newInstance(3)); + + for (int i = 0; i < 3; i++) { + TabLayout.Tab tab = binding.tab.newTab(); + TabViewBinding viewBinding = TabViewBinding.inflate(getLayoutInflater()); + + viewBinding.tvTabtext.setText(titles[i]); + viewBinding.ivTabIcon.setImageDrawable(tabIcon[i]); + + tab.setCustomView(viewBinding.getRoot()); + binding.tab.addTab(tab); + } + binding.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + + TabLayout.Tab tabAt = binding.tab.getTabAt(position); + if (tabAt != null) { + binding.tvAppTabname.setText(titles[position]); + tabAt.select(); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + binding.viewPager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) { + @NonNull + @Override + public Fragment getItem(int position) { + return fragmentList.get(position); + } + + @Override + public int getCount() { + return fragmentList.size(); + } + + @Nullable + @Override + public CharSequence getPageTitle(int position) { + return titles[position]; + } + }); + + TabLayout.Tab tabAt = binding.tab.getTabAt(1); + if (tabAt != null) + updateTab(tabAt, false); + binding.tab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { + updateTab(tab, true); + binding.viewPager.setCurrentItem(tab.getPosition()); + } + + @Override + public void onTabUnselected(TabLayout.Tab tab) { + updateTab(tab, false); + } + + @Override + public void onTabReselected(TabLayout.Tab tab) { + + } + }); + } + + private void initClick() { + binding.imSetPwd.setOnClickListener(v -> setBottomSheetView()); + } + + private void setBottomSheetView() { + if (isDestroyed()) + return; + + BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(ActivityMain.this); + View bottomSheetView = LayoutInflater.from(ActivityMain.this).inflate(R.layout.set_bottom_sheet_layout, null); + bottomSheetDialog.setContentView(bottomSheetView); + + ImageView ivClose = bottomSheetView.findViewById(R.id.ivClose); + TextView btnOption1 = bottomSheetView.findViewById(R.id.btnOption1); + TextView btnOption2 = bottomSheetView.findViewById(R.id.btnOption2); + + ivClose.setOnClickListener(v -> bottomSheetDialog.dismiss()); + + // 按钮1点击事件 + btnOption1.setOnClickListener(v -> { + Intent intent = new Intent(ActivityMain.this, ActivitySetPwd.class); + intent.putExtra(MyApplication.init_pwd_key, MyApplication.type_1); + startActivity(intent); + bottomSheetDialog.dismiss(); + }); + + // 按钮2点击事件 + btnOption2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + bottomSheetDialog.dismiss(); + } + }); + + bottomSheetDialog.show(); + } + + private void updateTab(TabLayout.Tab tab, boolean isSelected) { + View customView = tab.getCustomView(); + if (customView == null) return; + TextView tv = customView.findViewById(R.id.tv_tabtext); + tv.setSelected(isSelected); + ImageView iv = customView.findViewById(R.id.iv_tab_icon); + + iv.setSelected(isSelected); + + } + + private boolean checkPermission() { + boolean b = Common.checkPermission(this); + boolean canDrawOverlays = Common.getCanDrawOverlays(this); + return b && canDrawOverlays; + } + + private void openPermission() { + if (!checkPermission()) { + if (dialogPer == null) { + dialogPer = DialogPer.newInstance(); + dialogPer.setListener(this); + } + dialogPer.show(getSupportFragmentManager(), ""); + } + + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == MyApplication.reqCodeUsage) { + if (checkPermission()) { + dialogPer.dismiss(); + return; + } + boolean canDrawOverlays = Common.getCanDrawOverlays(this); + if (!canDrawOverlays) { + Common.goDrawOverlays(this, MyApplication.reqCodeOverlays); + } + } else if (requestCode == MyApplication.reqCodeOverlays) { + if (checkPermission()) { + dialogPer.dismiss(); + } else { + Toast.makeText(this, getString(R.string.text_permission_hint), Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public void onToSetting() { + boolean b = Common.checkPermission(this); + boolean canDrawOverlays = Common.getCanDrawOverlays(this); + + if (!b) { + Common.toSetUsagePermission(ActivityMain.this, MyApplication.reqCodeUsage); + } else { + + if (!canDrawOverlays) { + Common.goDrawOverlays(this, MyApplication.reqCodeOverlays); + } + } + + + } + + private void filterApps(String query) { + // 获取当前显示的Fragment + int position = binding.viewPager.getCurrentItem(); + Fragment fragment = fragmentList.get(position); + + // 如果Fragment是FragmentMy,则调用其filter方法 + if ((fragment instanceof FragmentMy)) { + ((FragmentMy) fragment).filter(query); + } + } + + @Override + public boolean onQueryTextSubmit(String query) { + + filterApps(query); + + return true; + } + + @Override + public boolean onQueryTextChange(String newText) { + filterApps(newText); + return true; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tool/app/protectorpro/activity/ActivitySetPwd.java b/app/src/main/java/com/tool/app/protectorpro/activity/ActivitySetPwd.java new file mode 100644 index 0000000..0224305 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/activity/ActivitySetPwd.java @@ -0,0 +1,283 @@ +package com.tool.app.protectorpro.activity; + +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.Editable; +import android.text.InputType; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.tool.app.protectorpro.MyApplication; +import com.tool.app.protectorpro.R; +import com.tool.app.protectorpro.customerview.MyLockView; +import com.tool.app.protectorpro.customerview.MyPasswordInputView; +import com.tool.app.protectorpro.databinding.ActivitySetPwdBinding; +import com.tool.app.protectorpro.listener.ListenerLock; + +public class ActivitySetPwd extends AppCompatActivity { + + private static final String TAG = "ActivitySetPwd"; + + private ActivitySetPwdBinding binding; + private int type; + private MyPasswordInputView passwordInputView; + private StringBuilder surePassword = new StringBuilder(); + private StringBuilder tempPassword = new StringBuilder(); + + private void initStatusBar() { + View decorView = getWindow().getDecorView(); + int flag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; + decorView.setSystemUiVisibility(flag); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivitySetPwdBinding.inflate(getLayoutInflater()); + initStatusBar(); + setContentView(binding.getRoot()); + passwordInputView = binding.layoutEt; + type = getIntent().getIntExtra(MyApplication.init_pwd_key, MyApplication.type_0); + initView(); + initInput(); + initClick(); + initKeyboard(); + } + + private void initView() { + // 0 设置 1 修改 2 确认 + switch (type) { + case MyApplication.type_0: + binding.imBack.setVisibility(View.GONE); + binding.tvPassName.setText(R.string.text_original_pwd); + // binding.tvTitle.setText(getString(R.string.text_original_pwd)); + binding.tvSub.setText(getString(R.string.text_original_pwd_describe)); + // binding.tvContinue.setText(getString(R.string.text_continue)); + break; + case MyApplication.type_1: + binding.imBack.setVisibility(View.VISIBLE); + binding.tvPassName.setText(R.string.sheet_change_password); + // binding.tvTitle.setText(getString(R.string.text_change_pwd)); + binding.tvSub.setText(getString(R.string.text_change_pwd_sub)); + // binding.tvContinue.setText(getString(R.string.text_save)); + break; + case MyApplication.type_2: + binding.imBack.setVisibility(View.VISIBLE); + binding.tvPassName.setText(R.string.text_confirm_pwd); + // binding.tvTitle.setText(getString(R.string.text_confirm_pwd)); + // binding.tvSub.setText(getString(R.string.text_change_pwd_sub)); + // binding.tvContinue.setText(getString(R.string.text_save)); + break; + } + updateEditText(); + } + + private void initInput() { + for (int i = 0; i < binding.layoutEt.getChildCount(); i++) { + EditText editText = (EditText) binding.layoutEt.getChildAt(i); + EditText nextEditText = null; + if ((i + 1) < binding.layoutEt.getChildCount()) { + nextEditText = (EditText) binding.layoutEt.getChildAt(i + 1); + } + + editText.setInputType(InputType.TYPE_NULL); + + EditText finalNextEditText = nextEditText; + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + if (s.length() > 0 && finalNextEditText != null) { + finalNextEditText.requestFocus(); + } + } + }); + } + + } + + private void initKeyboard() { + binding.lockSetPassword.setPinLockListener(new ListenerLock() { + @Override + public void onInPutComplete(String pin) { + Log.d(TAG, "onInPutComplete: " + pin); + + if (type == MyApplication.type_0 || type == MyApplication.type_1) { + Log.d(TAG, "在设置界面"); + if (pin.length() == 4) { + Log.d(TAG, "跳转到二次"); + type = MyApplication.type_2; + initView(); + } + + } else { + initView(); + Log.d(TAG, "在二次确认界面"); + checkPassword(); + } + } + + @Override + public void onNumberClickComplete(String keyValue) { + Log.d(TAG, "onNumberClickComplete: " + keyValue); + + if (type == MyApplication.type_0 || type == MyApplication.type_1) { + + if (tempPassword.length() < 4) { + tempPassword.append(keyValue); + passwordInputView.setInput(tempPassword); + Log.d(TAG, "tempPassword: " + tempPassword.toString()); + } + + } else if (type == MyApplication.type_2) { + if (surePassword.length() < 4) { + surePassword.append(keyValue); + passwordInputView.setInput(surePassword); + Log.d(TAG, "passwordBuilder: " + surePassword.toString()); + } + } + } + + @Override + public void onKeyBordDelete(int pin) { + + Log.d("fsdafsd", pin + "__dfs"); + if (pin == 1) { + surePassword.setLength(0); + tempPassword.setLength(0); + initView(); + } + + if (type == MyApplication.type_2) { + passwordInputView.setInput(surePassword); + // 删除 surePassword 中的字符 + if (surePassword.length() > 0) { + surePassword.deleteCharAt(surePassword.length() - 1); + passwordInputView.deleteLastInput(); + + + } + // 如果 surePassword 被删完了,将 type 设置为 type_0,并重新初始化视图和更新 EditText + if (surePassword.length() == 0) { + type = MyApplication.type_0; + initView(); + } + } else if (type == MyApplication.type_0 || type == MyApplication.type_1) { + passwordInputView.setInput(tempPassword); + // 删除 tempPassword 中的字符 + if (tempPassword.length() > 0) { + tempPassword.deleteCharAt(tempPassword.length() - 1); + passwordInputView.deleteLastInput(); + + } + } + Log.d(TAG, "onKeyBordDelete: Deleted last input. tempPassword: " + tempPassword.toString() + ", surePassword: " + surePassword.toString()); + } + + + }); + Log.d(TAG, "initKeyboard: Initialized pin lock listener"); + } + + private void initClick() { + binding.imBack.setOnClickListener(v -> { + finish(); + Log.d(TAG, "onClick: Back button clicked"); + }); + + binding.tvContinue.setOnClickListener(v -> { + // Placeholder for specific logic + Log.d(TAG, "onClick: Continue button clicked"); + }); + Log.d(TAG, "initClick: Initialized click listeners"); + } + + private void checkPassword() { + if (surePassword.toString().equals(tempPassword.toString())) { + savePassword(); + Log.d(TAG, "checkPassword: Passwords matched, saving password"); + } else { + + if ((surePassword.length() == tempPassword.length())) { + Toast.makeText(ActivitySetPwd.this, getString(R.string.text_pass_sure), Toast.LENGTH_SHORT).show(); + + } + Log.d(TAG, "checkPassword: Passwords do not match, showing toast"); + } + } + + private void savePassword() { + String password = surePassword.toString(); + if (password.length() == 4) { + MyApplication.updatePwd(password); + + switch (type) { + case MyApplication.type_0: + case MyApplication.type_2: + startActivity(new Intent(ActivitySetPwd.this, ActivityMain.class)); + break; + case MyApplication.type_1: + startActivity(new Intent(ActivitySetPwd.this, ActivityComplete.class)); + break; + } + finish(); + Log.d(TAG, "savePassword: Password saved successfully"); + } else { + Toast.makeText(ActivitySetPwd.this, getString(R.string.text_hint), Toast.LENGTH_SHORT).show(); + Log.d(TAG, "savePassword: Password length is not 4, showing hint toast"); + } + } + + + private void updateEditText() { + for (int i = 0; i < binding.layoutEt.getChildCount(); i++) { + EditText editText = (EditText) binding.layoutEt.getChildAt(i); + editText.setText(""); + } + + // 根据当前的 type 决定显示哪个密码 + String displayText = ""; + if (type == MyApplication.type_0 || type == MyApplication.type_1) { + + displayText = tempPassword.toString(); + } else if (type == MyApplication.type_2) { + displayText = surePassword.toString(); + } + + Log.d("dsafsdaf", tempPassword.toString() + "___" + surePassword.toString()); + // 设置 EditText 的内容 + for (int i = 0; i < displayText.length(); i++) { + if (i < binding.layoutEt.getChildCount()) { + EditText editText = (EditText) binding.layoutEt.getChildAt(i); + editText.setText(String.valueOf(displayText.charAt(i))); + } + } + + // 重新设置光标位置 + if (binding.layoutEt.getChildCount() > 0) { + EditText editText = (EditText) binding.layoutEt.getChildAt(0); + editText.requestFocus(); + } + + Log.d(TAG, "updateEditText: Updated EditText fields"); + } + + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/tool/app/protectorpro/activity/ActivityWel.java b/app/src/main/java/com/tool/app/protectorpro/activity/ActivityWel.java new file mode 100644 index 0000000..e53814b --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/activity/ActivityWel.java @@ -0,0 +1,62 @@ +package com.tool.app.protectorpro.activity; + +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.view.View; + +import androidx.appcompat.app.AppCompatActivity; + +import com.tool.app.protectorpro.MyApplication; +import com.tool.app.protectorpro.databinding.ActivityWelBinding; + +public class ActivityWel extends AppCompatActivity { + + private ActivityWelBinding binding; + + + private CountDownTimer countDownTimer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityWelBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + initBar(); + + countDownTimer = new CountDownTimer(2000L, 500L) { + @Override + public void onTick(long millisUntilFinished) { + + } + + @Override + public void onFinish() { + String pwd = MyApplication.getPwd(); + if (pwd.isEmpty()) { + startActivity(new Intent(ActivityWel.this, ActivitySetPwd.class)); + } else { + startActivity(new Intent(ActivityWel.this, ActivityMain.class)); + } + finish(); + + } + }; + countDownTimer.start(); + } + + private void initBar() { + View decorView = getWindow().getDecorView(); + int flag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; + decorView.setSystemUiVisibility(flag); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + countDownTimer.cancel(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tool/app/protectorpro/activity/DialogPer.java b/app/src/main/java/com/tool/app/protectorpro/activity/DialogPer.java new file mode 100644 index 0000000..1c46da8 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/activity/DialogPer.java @@ -0,0 +1,93 @@ +package com.tool.app.protectorpro.activity; + +import android.os.Bundle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; + +import com.tool.app.protectorpro.R; +import com.tool.app.protectorpro.databinding.DialogPermisBinding; +import com.tool.app.protectorpro.listener.onPermssionListener; +import com.tool.app.protectorpro.tools.Common; + +public class DialogPer extends DialogFragment { + private DialogPermisBinding layoutPermissionBinding; + + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + layoutPermissionBinding = DialogPermisBinding.inflate(getLayoutInflater()); + + getDialog().setCanceledOnTouchOutside(false); + getDialog().setCancelable(false); + + final Window window = getDialog().getWindow(); + window.setBackgroundDrawableResource(R.color.transparent); + window.getDecorView().setPadding(0, 0, 0, 0); + WindowManager.LayoutParams wlp = window.getAttributes(); + wlp.gravity = Gravity.CENTER; + wlp.width = WindowManager.LayoutParams.MATCH_PARENT; + wlp.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(wlp); + + + layoutPermissionBinding.llSet1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + if (!layoutPermissionBinding.tvSelect.isSelected()) { + listener.onToSetting(); + } + + } + }); + layoutPermissionBinding.llSet2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onToSetting(); + } + }); + + + return layoutPermissionBinding.getRoot(); + } + + + @Override + public void onResume() { + super.onResume(); + initView(); + } + + private onPermssionListener listener; + + public void setListener(onPermssionListener listener) { + this.listener = listener; + } + + public static DialogPer newInstance() { + return new DialogPer(); + } + + private void initView() { + boolean b = Common.checkPermission(getActivity()); + if (!b) { + layoutPermissionBinding.llSet1.setSelected(false); + layoutPermissionBinding.ivSet1.setVisibility(View.INVISIBLE); + } else { + layoutPermissionBinding.diaCheck.setSelected(true); + layoutPermissionBinding.llSet2.setSelected(false); + layoutPermissionBinding.ivSet1.setVisibility(View.VISIBLE); + } + } + + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/activity/FragmentMy.java b/app/src/main/java/com/tool/app/protectorpro/activity/FragmentMy.java new file mode 100644 index 0000000..b3be39b --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/activity/FragmentMy.java @@ -0,0 +1,82 @@ +package com.tool.app.protectorpro.activity; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.appcompat.widget.SearchView; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; + +import com.tool.app.protectorpro.databinding.FragmentMyBinding; +import com.tool.app.protectorpro.listadapter.AdapterAllApp; +import com.tool.app.protectorpro.mydb.DataApp; +import com.tool.app.protectorpro.mydb.MyDataBase; +import com.tool.app.protectorpro.tools.MyThread; + +import java.util.ArrayList; +import java.util.List; + +public class FragmentMy extends Fragment { + private int appType; + private FragmentMyBinding binding; + private static final String ARG_PARAM1 = "key_data"; + private AdapterAllApp adapterAllApp; + + public FragmentMy() { + } + + + public static FragmentMy newInstance(int appType) { + FragmentMy fragment = new FragmentMy(); + Bundle args = new Bundle(); + args.putInt(ARG_PARAM1, appType); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + appType = getArguments().getInt(ARG_PARAM1); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + binding = FragmentMyBinding.inflate(getLayoutInflater()); + + adapterAllApp = new AdapterAllApp(requireContext()); + binding.listApp.setAdapter(adapterAllApp); + binding.listApp.setLayoutManager(new LinearLayoutManager(requireContext())); + + MyThread.runIO(() -> { + List data; + if (appType == 1) { + data = MyDataBase.getInstance().getRoomDao().findByType(true, false); + } else if (appType == 2) { + data = MyDataBase.getInstance().getRoomDao().findByType(false, false); + } else if (appType == 3) { + data = MyDataBase.getInstance().getRoomDao().findByLock(true); + } else { + data = new ArrayList<>(); + } + + MyThread.runUI(() -> { + adapterAllApp.updateSyStemApp(data); + }); + }); + + return binding.getRoot(); + } + public void filter(String query) { + if (adapterAllApp != null) { + adapterAllApp.filter(query); + } + } + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/customerview/CustomBundle.kt b/app/src/main/java/com/tool/app/protectorpro/customerview/CustomBundle.kt new file mode 100644 index 0000000..e8bd318 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/customerview/CustomBundle.kt @@ -0,0 +1,19 @@ +package com.tool.app.protectorpro.customerview + +import android.graphics.drawable.Drawable + +class CustomBundle { + @JvmField + var textColor = 0 + @JvmField + var textSize = 0 + + + var isShowDeleteButton = false + @JvmField + var buttonSize = 0 + @JvmField + var backgroundDrawable: Drawable? = null + + +} \ No newline at end of file diff --git a/app/src/main/java/com/tool/app/protectorpro/customerview/LockSpace.java b/app/src/main/java/com/tool/app/protectorpro/customerview/LockSpace.java new file mode 100644 index 0000000..8a3faf3 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/customerview/LockSpace.java @@ -0,0 +1,45 @@ +package com.tool.app.protectorpro.customerview; + +import android.graphics.Rect; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +public class LockSpace extends RecyclerView.ItemDecoration { + + private final int HSpace; + + private final int mSpanCount; + private final boolean mInclude; + private final int mVSpace; + + public LockSpace(int horizontalSpaceWidth, int verticalSpaceHeight, int spanCount, boolean includeEdge) { + this.HSpace = horizontalSpaceWidth; + this.mVSpace = verticalSpaceHeight; + this.mSpanCount = spanCount; + this.mInclude = includeEdge; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + + int position = parent.getChildAdapterPosition(view); + int 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; + } + } + } +} diff --git a/app/src/main/java/com/tool/app/protectorpro/customerview/MyDots.java b/app/src/main/java/com/tool/app/protectorpro/customerview/MyDots.java new file mode 100644 index 0000000..b257cab --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/customerview/MyDots.java @@ -0,0 +1,102 @@ +package com.tool.app.protectorpro.customerview; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; + +import androidx.core.view.ViewCompat; + +import com.tool.app.protectorpro.R; +import com.tool.app.protectorpro.tools.Common; + + +public class MyDots extends LinearLayout { + + + private static final int DEFAULT_PIN_LENGTH = 4; + private int mPinLength; + + + private int mPreviousLength; + private int mDotDiameter; + private int mDotSpacing; + private int mFillDrawable; + private int mEmptyDrawable; + + private void initView(Context context) { + ViewCompat.setLayoutDirection(this, ViewCompat.LAYOUT_DIRECTION_LTR); + for (int i = 0; i < mPinLength; i++) { + View dot = new View(context); + emptyDot(dot); + + LayoutParams params = new LayoutParams(mDotDiameter, + mDotDiameter); + params.setMargins(mDotSpacing, 0, mDotSpacing, 0); + dot.setLayoutParams(params); + + addView(dot); + } + + } + + public MyDots(Context context) { + this(context, null); + } + + public MyDots(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public MyDots(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyLock); + + try { + mDotDiameter = (int) typedArray.getDimension(R.styleable.MyLock_dotDiameter, Common.getPx(getContext(), R.dimen.default_dot_diameter)); + mDotSpacing = (int) typedArray.getDimension(R.styleable.MyLock_dotSpacing, Common.getPx(getContext(), R.dimen.default_dot_spacing)); + mFillDrawable = typedArray.getResourceId(R.styleable.MyLock_dotFilledBackground, + R.drawable.oval_black); + mEmptyDrawable = typedArray.getResourceId(R.styleable.MyLock_dotEmptyBackground, + R.drawable.pwd_bg); + mPinLength = typedArray.getInt(R.styleable.MyLock_pinLength, DEFAULT_PIN_LENGTH); + } finally { + typedArray.recycle(); + } + + initView(context); + } + + + private void emptyDot(View dot) { + dot.setBackgroundResource(mEmptyDrawable); + dot.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start(); + } + + private void fillDot(View dot) { + dot.setBackgroundResource(mFillDrawable); + dot.animate().scaleX(1.2f).scaleY(1.2f).setDuration(100).start(); + } + + + void updateDot(int length) { + if (length > 0) { + if (length > mPreviousLength) { + fillDot(getChildAt(length - 1)); + } else { + emptyDot(getChildAt(length)); + } + mPreviousLength = length; + } else { + for (int i = 0; i < getChildCount(); i++) { + View v = getChildAt(i); + emptyDot(v); + } + mPreviousLength = 0; + } + + } + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/customerview/MyLockView.java b/app/src/main/java/com/tool/app/protectorpro/customerview/MyLockView.java new file mode 100644 index 0000000..e2ab51c --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/customerview/MyLockView.java @@ -0,0 +1,226 @@ +package com.tool.app.protectorpro.customerview; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.tool.app.protectorpro.MyApplication; +import com.tool.app.protectorpro.R; +import com.tool.app.protectorpro.listadapter.AdapterLockView; +import com.tool.app.protectorpro.listener.ListenerLock; +import com.tool.app.protectorpro.tools.Common; + +public class MyLockView extends RecyclerView { + private String mPin = ""; + private int mPinLength; + private int mHorizontalSpacing, mVerticalSpacing; + private int mTextColor; + private int mTextSize, mButtonSize; + private Drawable mButtonBgDraw; + private AdapterLockView mAdapter; + private ListenerLock mPinLockListener; + private CustomBundle mCustomBundle; + + private boolean mShowDelete; + private static final int DEFAULT_PWD_LENGTH = 4; + private MyDots mMyDots; + + + private AdapterLockView.OnNumberClickListener numberClickListener + = new AdapterLockView.OnNumberClickListener() { + @Override + public void onNumberClicked(int keyValue) { + + + if (mPinLockListener != null) { + mPinLockListener.onNumberClickComplete(String.valueOf(keyValue)); + } + + if (mPin.length() < getPinLength()) { + mPin = mPin.concat(String.valueOf(keyValue)); + + if (isIndicatorDotsAttached()) { + mMyDots.updateDot(mPin.length()); + + } + + if (mPin.length() == 1) { + mAdapter.setPinLength(mPin.length()); + mAdapter.notifyItemChanged(mAdapter.getItemCount() - 1); + } + + if (mPinLockListener != null) { + if (mPin.length() == mPinLength) { + mPinLockListener.onInPutComplete(mPin); + } else { + + } + } + } else { + if (!isShowDeleteButton()) { + resetPinLockView(); + mPin = mPin.concat(String.valueOf(keyValue)); + + if (isIndicatorDotsAttached()) { + mMyDots.updateDot(mPin.length()); + } + + if (mPinLockListener != null) { +// mPinLockListener.onPinChange(mPin.length(), mPin); + } + + } else { + if (mPinLockListener != null) { + mPinLockListener.onInPutComplete(mPin); + } + } + } + } + }; + + private AdapterLockView.OnDeleteClickListener mOnDeleteClickListener + = new AdapterLockView.OnDeleteClickListener() { + @Override + public void onDeleteClicked() { + Log.d("key_delete", mPin.length() + "..."); + + if (!mPin.isEmpty()) { + mPinLockListener.onKeyBordDelete(mPin.length()); + + mPin = mPin.substring(0, mPin.length() - 1); + + if (isIndicatorDotsAttached()) { + mMyDots.updateDot(mPin.length()); + + } + + if (mPin.length() == 0) { + mAdapter.setPinLength(mPin.length()); + mAdapter.notifyItemChanged(mAdapter.getItemCount() - 1); + } + + if (mPinLockListener != null) { + if (mPin.length() == 0) { +// mPinLockListener.onEmpty(); + clearInternalPin(); + } else { +// mPinLockListener.onPinChange(mPin.length(), mPin); + } + } + } else { + if (mPinLockListener != null) { + + + + } + } + } + + }; + + public MyLockView(Context context) { + super(context); + init(null, 0); + } + + public MyLockView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(attrs, 0); + } + + public MyLockView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(attrs, defStyle); + } + + private void init(AttributeSet attributeSet, int defStyle) { + + TypedArray typedArray = getContext().obtainStyledAttributes(attributeSet, R.styleable.MyLock); + + try { + mPinLength = typedArray.getInt(R.styleable.MyLock_pinLength, DEFAULT_PWD_LENGTH); + mHorizontalSpacing = (int) typedArray.getDimension(R.styleable.MyLock_keypadHorizontalSpacing, Common.getPx(getContext(), R.dimen.default_horizontal_spacing)); + mVerticalSpacing = (int) typedArray.getDimension(R.styleable.MyLock_keypadVerticalSpacing, Common.getPx(getContext(), R.dimen.default_vertical_spacing)); + mTextColor = typedArray.getColor(R.styleable.MyLock_keypadTextColor, Common.getColor(getContext(), R.color.color_keyboard_num)); + mTextSize = (int) typedArray.getDimension(R.styleable.MyLock_keypadTextSize, Common.getPx(getContext(), R.dimen.default_text_size)); + mButtonSize = (int) typedArray.getDimension(R.styleable.MyLock_keypadButtonSize, Common.getPx(getContext(), R.dimen.default_button_size)); + mButtonBgDraw = typedArray.getDrawable(R.styleable.MyLock_keypadButtonBackgroundDrawable); + + mShowDelete = typedArray.getBoolean(R.styleable.MyLock_keypadShowDeleteButton, true); + } finally { + typedArray.recycle(); + } + + mCustomBundle = new CustomBundle(); + mCustomBundle.textColor = mTextColor; + mCustomBundle.textSize = mTextSize; + mCustomBundle.buttonSize = mButtonSize; + mCustomBundle.backgroundDrawable = mButtonBgDraw; + mCustomBundle.setShowDeleteButton(mShowDelete); + + + initView(); + } + + private void initView() { + mAdapter = new AdapterLockView(); + setLayoutManager(new GridLayoutManager(getContext(), 3)); + + + mAdapter.setOnItemClickListener(numberClickListener); + mAdapter.setOnDeleteClickListener(mOnDeleteClickListener); + mAdapter.setCustomizationOptions(mCustomBundle); + setAdapter(mAdapter); + + addItemDecoration(new LockSpace(mHorizontalSpacing, mVerticalSpacing, 3, false)); + setOverScrollMode(OVER_SCROLL_NEVER); + } + + + public void setPinLockListener(ListenerLock pinLockListener) { + this.mPinLockListener = pinLockListener; + } + + public int getPinLength() { + return mPinLength; + } + + public boolean isShowDeleteButton() { + return mShowDelete; + } + + private void clearInternalPin() { + mPin = ""; + } + + + public void resetPinLockView() { + clearInternalPin(); + mAdapter.setPinLength(mPin.length()); + mAdapter.notifyItemChanged(mAdapter.getItemCount() - 1); + + if (mMyDots != null) { + mMyDots.updateDot(mPin.length()); + } + } + + public boolean isIndicatorDotsAttached() { + return mMyDots != null; + } + + + public void setPinLength(){ + + + } + + public void attachIndicatorDots(MyDots mMyDots) { + this.mMyDots = mMyDots; + } +} diff --git a/app/src/main/java/com/tool/app/protectorpro/customerview/MyPasswordInputView.java b/app/src/main/java/com/tool/app/protectorpro/customerview/MyPasswordInputView.java new file mode 100644 index 0000000..60067c8 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/customerview/MyPasswordInputView.java @@ -0,0 +1,85 @@ +package com.tool.app.protectorpro.customerview; + +import android.content.Context; +import android.text.InputFilter; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.EditText; +import android.widget.LinearLayout; + +import androidx.annotation.Nullable; + +import com.tool.app.protectorpro.R; + +public class MyPasswordInputView extends LinearLayout { + + private EditText[] mEditTexts = new EditText[4]; + + public MyPasswordInputView(Context context) { + this(context, null); + } + + public MyPasswordInputView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public MyPasswordInputView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + LayoutInflater.from(context).inflate(R.layout.custom_password_input_view, this, true); + mEditTexts[0] = findViewById(R.id.et1); + mEditTexts[1] = findViewById(R.id.et2); + mEditTexts[2] = findViewById(R.id.et3); + mEditTexts[3] = findViewById(R.id.et4); + setupEditTexts(); + } + + private void setupEditTexts() { + for (EditText editText : mEditTexts) { + editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1)}); + } + } + + + public void appendInput(String input) { + String currentInput = getInput(); + String newInput = currentInput + input; + + clearInput(); + + for (int i = 0; i < newInput.length() && i < mEditTexts.length; i++) { + mEditTexts[i].setText(String.valueOf(newInput.charAt(i))); + } + } + + public void deleteLastInput() { + for (int i = mEditTexts.length - 1; i >= 0; i--) { + EditText editText = mEditTexts[i]; + if (editText.getText().length() > 0) { + editText.setText(""); + break; + } + } + } + + public String getInput() { + StringBuilder stringBuilder = new StringBuilder(); + for (EditText editText : mEditTexts) { + stringBuilder.append(editText.getText().toString()); + } + return stringBuilder.toString(); + } + + public void clearInput() { + for (EditText editText : mEditTexts) { + editText.setText(""); + } + } + + // 新增一个方法来设置输入内容 + public void setInput(StringBuilder input) { + clearInput(); + for (int i = 0; i < input.length() && i < mEditTexts.length; i++) { + mEditTexts[i].setText(String.valueOf(input.charAt(i))); + } + } +} diff --git a/app/src/main/java/com/tool/app/protectorpro/listadapter/AdapterAllApp.java b/app/src/main/java/com/tool/app/protectorpro/listadapter/AdapterAllApp.java new file mode 100644 index 0000000..52ef817 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/listadapter/AdapterAllApp.java @@ -0,0 +1,134 @@ +package com.tool.app.protectorpro.listadapter; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.util.Log; +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.annotation.NonNull; +import androidx.appcompat.widget.SwitchCompat; +import androidx.recyclerview.widget.RecyclerView; + +import com.tool.app.protectorpro.R; +import com.tool.app.protectorpro.mydb.DataApp; +import com.tool.app.protectorpro.mydb.MyDataBase; +import com.tool.app.protectorpro.tools.MyThread; + +import java.util.ArrayList; +import java.util.List; +public class AdapterAllApp extends RecyclerView.Adapter { + + private List list = new ArrayList<>(); + private List filterList = new ArrayList<>(); + private Context mContext; + private PackageManager packageManager; + + public AdapterAllApp(Context context) { + mContext = context; + packageManager = context.getPackageManager(); + } + + public void updateSyStemApp(List infoList) { + list.clear(); + filterList.clear(); + if (infoList != null && !infoList.isEmpty()) { + list.addAll(infoList); + filterList.addAll(list); + Log.d("AdapterAllApp", "List updated, size: " + list.size()); + } else { + Log.d("AdapterAllApp", "Received empty or null list"); + } + notifyDataSetChanged(); + } + + public void filter(String query) { + filterList.clear(); + if (query.isEmpty()) { + filterList.addAll(list); + if (!list.isEmpty()) { + Log.d("AdapterAllApp", "List size: " + list.size()); + Log.d("AdapterAllApp", "First item: " + list.get(0).getAppName()); + } else { + Log.d("AdapterAllApp", "List is empty"); + } + } else { + for (DataApp item : list) { + if (item.getAppName().toLowerCase().contains(query.toLowerCase())) { + filterList.add(item); + Log.d("AdapterAllApp", "Filtered item: " + item.getAppName()); + } + } + } + notifyDataSetChanged(); + } + + @NonNull + @Override + public AppViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + AppViewHolder appViewHolder = new AppViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_systapp, parent, false)); + return appViewHolder; + } + + @Override + public void onBindViewHolder(@NonNull AppViewHolder holder, int position) { + holder.switchCompat.setOnCheckedChangeListener(null); + DataApp dataApp = filterList.get(position); // 使用filterList + String appName = dataApp.getAppName(); + boolean lock = dataApp.isLock(); + holder.switchCompat.setChecked(lock); + holder.switchCompat.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> { + MyThread.runIO(() -> { + dataApp.setLock(isChecked); + MyDataBase.getInstance().getRoomDao().updateData(dataApp); + }); + String format; + 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(); + }); + + try { + Drawable appLogo = getLogo(dataApp.getPackageName()); + holder.imageView.setImageDrawable(appLogo); + } catch (PackageManager.NameNotFoundException e) { + // Handle exception + } + + holder.textView.setText(appName); + } + + private Drawable getLogo(String packageName) throws PackageManager.NameNotFoundException { + ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES); + return packageManager.getApplicationIcon(appInfo); + } + + @Override + public int getItemCount() { + return filterList.size(); // 使用filterList + } + + public static class AppViewHolder extends RecyclerView.ViewHolder { + + private ImageView imageView; + private TextView textView; + private SwitchCompat switchCompat; + + public AppViewHolder(@NonNull View itemView) { + super(itemView); + imageView = itemView.findViewById(R.id.logo); + textView = itemView.findViewById(R.id.name); + switchCompat = itemView.findViewById(R.id.app_switch); + } + } +} diff --git a/app/src/main/java/com/tool/app/protectorpro/listadapter/AdapterLockView.java b/app/src/main/java/com/tool/app/protectorpro/listadapter/AdapterLockView.java new file mode 100644 index 0000000..e8dc6c9 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/listadapter/AdapterLockView.java @@ -0,0 +1,186 @@ +package com.tool.app.protectorpro.listadapter; + + + +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 android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.tool.app.protectorpro.R; +import com.tool.app.protectorpro.customerview.CustomBundle; +import com.tool.app.protectorpro.customerview.CustomBundle; + +public class AdapterLockView extends RecyclerView.Adapter { + + private static final int TYPE_NUMBER = 0; + + private OnNumberClickListener mOnNumberListener; + private OnDeleteClickListener mOnDeleteListener; + + private static final int VIEW_TYPE_DELETE = 1; + private CustomBundle mCustomBundle; + private int mCurLength; + + private int[] mKeyValues; + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + RecyclerView.ViewHolder viewHolder; + LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + + if (viewType == TYPE_NUMBER) { + View view = inflater.inflate(R.layout.item_number, parent, false); + viewHolder = new NumberViewHolder(view); + } else { + View view = inflater.inflate(R.layout.item_delete, parent, false); + viewHolder = new DeleteViewHolder(view); + } + return viewHolder; + } + public AdapterLockView() { + this.mKeyValues = getKeyValues(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}); + } + + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder.getItemViewType() == TYPE_NUMBER) { + NumberViewHolder vh1 = (NumberViewHolder) holder; + setNumberBtn(vh1, position); + } + } + + private void setNumberBtn(NumberViewHolder holder, int position) { + if (holder != null) { + if (position == 9) { + holder.mNumberButton.setVisibility(View.GONE); + } else { + holder.mNumberButton.setText(String.valueOf(mKeyValues[position])); + holder.mNumberButton.setVisibility(View.VISIBLE); + holder.mNumberButton.setTag(mKeyValues[position]); + } + + if (mCustomBundle != null) { + holder.mNumberButton.setTextColor(mCustomBundle.textColor); + if (mCustomBundle.backgroundDrawable != null) { + holder.mNumberButton.setBackground(mCustomBundle.backgroundDrawable); + } + holder.mNumberButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, + mCustomBundle.textSize); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + mCustomBundle.buttonSize, + mCustomBundle.buttonSize); + holder.mNumberButton.setLayoutParams(params); + } + } + } + + + + @Override + public int getItemCount() { + return 12; + } + + @Override + public int getItemViewType(int position) { + if (position == getItemCount() - 1) { + return VIEW_TYPE_DELETE; + } + return TYPE_NUMBER; + } + + + + public void setPinLength(int pinLength) { + this.mCurLength = pinLength; + } + + + + private int[] getKeyValues(int[] keyValues) { + int[] adjustedKeyValues = new int[keyValues.length + 1]; + for (int i = 0; i < keyValues.length; i++) { + if (i < 9) { + adjustedKeyValues[i] = keyValues[i]; + } else { + adjustedKeyValues[i] = -1; + adjustedKeyValues[i + 1] = keyValues[i]; + } + } + return adjustedKeyValues; + } + + + + public void setOnItemClickListener(OnNumberClickListener onNumberClickListener) { + this.mOnNumberListener = onNumberClickListener; + } + + + + public void setOnDeleteClickListener(OnDeleteClickListener onDeleteClickListener) { + this.mOnDeleteListener = onDeleteClickListener; + } + + + + public void setCustomizationOptions(CustomBundle customBundle) { + this.mCustomBundle = customBundle; + } + + public class NumberViewHolder extends RecyclerView.ViewHolder { + TextView mNumberButton; + + public NumberViewHolder(final View itemView) { + super(itemView); + mNumberButton = (TextView) itemView.findViewById(R.id.deleteLayout); + mNumberButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mOnNumberListener != null) { + mOnNumberListener.onNumberClicked((Integer) v.getTag()); + } + } + }); + } + } + public interface OnNumberClickListener { + void onNumberClicked(int keyValue); + } + + public interface OnDeleteClickListener { + void onDeleteClicked(); + } + public class DeleteViewHolder extends RecyclerView.ViewHolder { + LinearLayout mDeleteLayout; + ImageView mDeleteImage; + + public DeleteViewHolder(final View itemView) { + super(itemView); + mDeleteLayout = (LinearLayout) itemView.findViewById(R.id.deleteLayout); + mDeleteImage = (ImageView) itemView.findViewById(R.id.deleteImage); + + if (mCustomBundle.isShowDeleteButton() && mCurLength > 0) { + mDeleteLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mOnDeleteListener != null) { + mOnDeleteListener.onDeleteClicked(); + } + } + }); + + } + } + } + + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/listener/ListenerDao.kt b/app/src/main/java/com/tool/app/protectorpro/listener/ListenerDao.kt new file mode 100644 index 0000000..b3e66eb --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/listener/ListenerDao.kt @@ -0,0 +1,33 @@ +package com.tool.app.protectorpro.listener + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Update +import com.tool.app.protectorpro.mydb.DataApp + +@Dao +interface ListenerDao { + @Delete + fun deleteData(dataApp: DataApp) + + @Query("select * from DataApp where packageName=:packName") + fun findByPackName(packName: String): DataApp? + + @Query("select * from DataApp where isSyStem=:system AND isRecommend = :recommend") + fun findByType(system: Boolean, recommend: Boolean): List? + + @Update + fun updateData(dataApp: DataApp) + + @Insert(onConflict = OnConflictStrategy.IGNORE) + fun insertData(dataApp: DataApp) + + @Query("select * from DataApp") + fun findApp(): List? + + @Query("select * from DataApp where isLock =:isLock") + fun findByLock(isLock: Boolean): List? +} \ No newline at end of file diff --git a/app/src/main/java/com/tool/app/protectorpro/listener/ListenerLock.java b/app/src/main/java/com/tool/app/protectorpro/listener/ListenerLock.java new file mode 100644 index 0000000..8d57e46 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/listener/ListenerLock.java @@ -0,0 +1,12 @@ +package com.tool.app.protectorpro.listener; + + +public interface ListenerLock { + + + void onInPutComplete(String pin); + + void onNumberClickComplete(String keyValue); + + void onKeyBordDelete( int pin); +} diff --git a/app/src/main/java/com/tool/app/protectorpro/listener/onPermssionListener.java b/app/src/main/java/com/tool/app/protectorpro/listener/onPermssionListener.java new file mode 100644 index 0000000..8fa52e5 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/listener/onPermssionListener.java @@ -0,0 +1,8 @@ +package com.tool.app.protectorpro.listener; + + +public interface onPermssionListener { + + void onToSetting(); + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/mydb/DataApp.java b/app/src/main/java/com/tool/app/protectorpro/mydb/DataApp.java new file mode 100644 index 0000000..4958a7f --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/mydb/DataApp.java @@ -0,0 +1,74 @@ +package com.tool.app.protectorpro.mydb; + +import androidx.room.Entity; +import androidx.room.Index; +import androidx.room.PrimaryKey; + +import com.tool.app.protectorpro.MyApplication; + + +@Entity(tableName = MyApplication.Table_Name,indices = {@Index(value = {"packageName"}, unique = true)}) +public class DataApp { + + @PrimaryKey(autoGenerate = true) + private int id; + private String packageName; + + private String appName; + + private boolean isLock = false; + + private boolean isSyStem ; + + private boolean isRecommend = false; + + public boolean isRecommend() { + return isRecommend; + } + + public void setRecommend(boolean recommend) { + isRecommend = recommend; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public void setSyStem(boolean syStem) { + isSyStem = syStem; + } + + public boolean isSyStem() { + return isSyStem; + } + + + public void setAppName(String appName) { + this.appName = appName; + } + + public void setLock(boolean lock) { + isLock = lock; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + + public String getAppName() { + return appName; + } + + public String getPackageName() { + return packageName; + } + + public boolean isLock() { + return isLock; + } +} diff --git a/app/src/main/java/com/tool/app/protectorpro/mydb/MyDataBase.java b/app/src/main/java/com/tool/app/protectorpro/mydb/MyDataBase.java new file mode 100644 index 0000000..dab0607 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/mydb/MyDataBase.java @@ -0,0 +1,28 @@ +package com.tool.app.protectorpro.mydb; + +import androidx.room.Database; +import androidx.room.Room; +import androidx.room.RoomDatabase; + +import com.tool.app.protectorpro.MyApplication; +import com.tool.app.protectorpro.listener.ListenerDao; + +@Database( + entities = {DataApp.class}, + version = MyApplication.DB_Version, + exportSchema = false +) +public abstract class MyDataBase extends RoomDatabase { + + private static MyDataBase INSTANCE; + + public static synchronized MyDataBase getInstance() { + if (INSTANCE == null) { + INSTANCE = Room.databaseBuilder(MyApplication.appContext, MyDataBase.class, MyApplication.DB_Name).build(); + } + return INSTANCE; + } + + public abstract ListenerDao getRoomDao(); + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/service/LockService.java b/app/src/main/java/com/tool/app/protectorpro/service/LockService.java new file mode 100644 index 0000000..e2112da --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/service/LockService.java @@ -0,0 +1,65 @@ +package com.tool.app.protectorpro.service; + +import android.app.IntentService; +import android.content.Intent; + +import androidx.annotation.Nullable; + +import com.tool.app.protectorpro.mydb.DataApp; +import com.tool.app.protectorpro.mydb.MyDataBase; +import com.tool.app.protectorpro.tools.LockManager; +import com.tool.app.protectorpro.tools.Common; +import com.tool.app.protectorpro.tools.MyThread; + +import java.util.Objects; + +public class LockService extends IntentService { + + private String lastLockPackName = ""; + private LockManager instance; + private Boolean checkTop = true; + + @Override + protected void onHandleIntent(@Nullable Intent intent) { + instance = LockManager.getInstance(this); + while (checkTop) { + String packageName = Common.checkUsageStats(this); + if(Objects.equals(packageName, "")){ + continue; + } + DataApp dataApp = MyDataBase.getInstance().getRoomDao().findByPackName(packageName); + if(dataApp == null){ + MyThread.runUI(()->{ + instance.unLock(); + }); + lastLockPackName = packageName; + + continue; + } + if(Objects.equals(packageName, lastLockPackName)){ + continue; + } + if (dataApp.isLock() ) { + if(!Objects.equals(packageName, lastLockPackName)){ + MyThread.runUI(()->{ + instance.showLockView(); + }); + }else { + } + }else { + + MyThread.runUI(()->{ + instance.unLock(); + }); + } + lastLockPackName = packageName; + } + + } + public LockService() { + super(""); + } + + + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/tools/Common.java b/app/src/main/java/com/tool/app/protectorpro/tools/Common.java new file mode 100644 index 0000000..f71241e --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/tools/Common.java @@ -0,0 +1,219 @@ +package com.tool.app.protectorpro.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.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; +import android.text.TextUtils; + +import androidx.annotation.ColorRes; +import androidx.annotation.DimenRes; +import androidx.core.content.ContextCompat; + +import com.tool.app.protectorpro.mydb.DataApp; +import com.tool.app.protectorpro.mydb.MyDataBase; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +public class Common { + public static float getPx(Context context, @DimenRes int id) { + return context.getResources().getDimension(id); + } + + private static void addDb(List list, boolean isSystem, boolean isUpdate) { +// HashSet randomIndex = getRandomIndex(list.size()); + + for (int i = 0; i < list.size(); i++) { + DataApp dataApp = list.get(i); + dataApp.setSyStem(isSystem); + if (isUpdate) { + DataApp dataApp1 = MyDataBase.getInstance().getRoomDao().findByPackName(dataApp.getPackageName()); + if (dataApp1 == null) { + MyDataBase.getInstance().getRoomDao().insertData(dataApp); + + } + } else { +// boolean contains = randomIndex.contains(i); + dataApp.setRecommend(false); + MyDataBase.getInstance().getRoomDao().insertData(dataApp); + + } + } + } + + public static List getAppList(Context context, boolean isUpdate) { + PackageManager packageManager = context.getPackageManager(); + Intent intent = new Intent(Intent.ACTION_MAIN, null); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + List resolveInfos = packageManager.queryIntentActivities(intent, 0); + + List systemAppList = new ArrayList<>(); + List threeAppList = new ArrayList<>(); + + for (int i = 0; i < resolveInfos.size(); i++) { + ResolveInfo resolveInfo = resolveInfos.get(i); + String packageName = resolveInfo.activityInfo.packageName; + if (Objects.equals(packageName, context.getPackageName())) { + continue; + } + ApplicationInfo appInfo; + try { + appInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES); + String appName = packageManager.getApplicationLabel(appInfo).toString(); + + DataApp dataApp = new DataApp(); + dataApp.setPackageName(packageName); + dataApp.setAppName(appName); + boolean systemApp = checkSystemApp(context, packageName); + if (systemApp) { + systemAppList.add(dataApp); + } else { + threeAppList.add(dataApp); + } + } catch (PackageManager.NameNotFoundException nameNotFoundException) { + + } + + + } + + List uniqueSystemList = removeDuplApp(systemAppList); + List uniqueThreeList = removeDuplApp(threeAppList); + + + MyThread.runIO(() -> { + addDb(uniqueSystemList, true, isUpdate); + addDb(uniqueThreeList, false, isUpdate); + + }); + + return uniqueThreeList; + + + } + + + public static int getColor(Context context, @ColorRes int id) { + return ContextCompat.getColor(context, id); + } + + +// private static HashSet getRandomIndex(int size) { +// Random random = new Random(); +// HashSet uniqueNumbers = new HashSet<>(); +// while (uniqueNumbers.size() < 4) { +// int randomNumber = random.nextInt(size + 1); +// uniqueNumbers.add(randomNumber); +// } +// return uniqueNumbers; +// +// } + + private static boolean checkSystemApp(Context context, String packageName) { + + try { + PackageInfo info = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES); + if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + return true; + } + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + + return false; + } + + + public static List removeDuplApp(List list) { + HashMap hashMap = new HashMap<>(); + for (DataApp dataApp : list) { + if (!hashMap.containsKey(dataApp.getPackageName())) { + hashMap.put(dataApp.getPackageName(), dataApp); + } + } + List data = new ArrayList<>(); + for (HashMap.Entry entry : hashMap.entrySet()) { + data.add(entry.getValue()); + } + return data; + } + + + public static String checkUsageStats(Context context) { + UsageStatsManager sUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE); + long endTime = System.currentTimeMillis(); + long beginTime = endTime - 10000; + String result = ""; + UsageEvents.Event event = new UsageEvents.Event(); + UsageEvents usageEvents = sUsageStatsManager.queryEvents(beginTime, endTime); + while (usageEvents.hasNextEvent()) { + usageEvents.getNextEvent(event); + if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) { + result = event.getPackageName(); + } + } + if (!TextUtils.isEmpty(result)) { + return result; + } else { + return ""; + } + } + + public static Boolean delUnInstallApp(Context context, String packName) { + PackageManager packageManager = context.getPackageManager(); + try { + packageManager.getApplicationInfo(packName, PackageManager.GET_UNINSTALLED_PACKAGES); + return false; + } catch (PackageManager.NameNotFoundException nameNotFoundException) { + return true; + } + } + + + public static boolean checkPermission(Context context) { + + // 检查当前应用是否具有 "android:get_usage_stats" 权限 + AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + int mode = 0; + mode = appOps.checkOpNoThrow("android:get_usage_stats", android.os.Process.myUid(), context.getPackageName()); + return mode == AppOpsManager.MODE_ALLOWED; + } + + public static void goDrawOverlays(Activity activity, int requestCode) { + Intent intent = new 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 + Uri uri = Uri.fromParts("package", activity.getPackageName(), null); + intent.setData(uri); +// intent.setData(Uri.parse("package:" + activity.getPackageName())); + } + activity.startActivityForResult(intent, requestCode); + } + + + public static void toSetUsagePermission(Activity context, int requestCode) { + Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); +// Uri uri = Uri.fromParts("package", context.getPackageName(), null); +// intent.setData(uri); + context.startActivityForResult(intent, requestCode); + } + + public static boolean getCanDrawOverlays(Context context) { + return Settings.canDrawOverlays(context); + } +} diff --git a/app/src/main/java/com/tool/app/protectorpro/tools/LockManager.java b/app/src/main/java/com/tool/app/protectorpro/tools/LockManager.java new file mode 100644 index 0000000..fe4a54e --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/tools/LockManager.java @@ -0,0 +1,168 @@ +package com.tool.app.protectorpro.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 android.widget.FrameLayout; +import android.widget.TextView; + + +import com.google.android.material.snackbar.Snackbar; +import com.tool.app.protectorpro.MyApplication; +import com.tool.app.protectorpro.R; +import com.tool.app.protectorpro.customerview.MyDots; +import com.tool.app.protectorpro.listener.ListenerLock; +import com.tool.app.protectorpro.customerview.MyLockView; + +import java.util.Objects; + +public class LockManager { + + private static LockManager lockManager; + private Context mContext; + + private View mView; + + private WindowManager windowManager; + + + private WindowManager.LayoutParams layoutParams; + + private MyLockView lockView; + + public LockManager(Context context) { + mContext = context; + mView = LayoutInflater.from(context).inflate(R.layout.float_view, null, false); + windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + + + initView(); + + MyDots dots = mView.findViewById(R.id.indicator_dots); + lockView = mView.findViewById(R.id.pin_lock_view); + lockView.attachIndicatorDots(dots); + lockView.setPinLockListener(new ListenerLock() { + @Override + public void onNumberClickComplete(String keyValue) { + + } + + @Override + public void onKeyBordDelete(int pin) { + + } + + @Override + public void onInPutComplete(String pin) { + + String pwd = MyApplication.getPwd(); + if (Objects.equals(pin, pwd)) { + unLock(); + } else { + lockView.resetPinLockView(); + + // Toast.makeText(mContext,"Password error",Toast.LENGTH_SHORT).show(); + + // showCustomSnackbar(mView, "Password error", Color.argb(1, 224, 224, 224)); + + } + } + }); + } + + public static LockManager getInstance(Context context) { + if (lockManager == null) { + lockManager = new LockManager(context); + } + return lockManager; + + } + + private void showCustomSnackbar(View view, String message, int backgroundColor) { + Snackbar snackbar = Snackbar.make(view, "", Snackbar.LENGTH_LONG); + + // 获取Snackbar的View + View snackbarView = snackbar.getView(); + + // 获取Snackbar的父布局 + ViewGroup snackbarLayout = (ViewGroup) snackbarView.findViewById(com.google.android.material.R.id.snackbar_text).getParent(); + + // 移除默认的TextView + snackbarLayout.removeAllViews(); + + // 自定义布局 + LayoutInflater inflater = LayoutInflater.from(view.getContext()); + View customView = inflater.inflate(R.layout.custom_float_snackbar, null); + + // 设置背景颜色 + snackbarView.setBackgroundColor(backgroundColor); + + // 设置描述文字 + TextView snackbarText = customView.findViewById(R.id.snackbar_text); + snackbarText.setText(message); + + // 将自定义布局添加到Snackbar的布局中 + snackbarLayout.addView(customView); + + // 设置居中 + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) snackbarView.getLayoutParams(); + params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; + snackbarView.setLayoutParams(params); + + snackbar.show(); + } + + private void initView() { + int type = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + } else { + type = WindowManager.LayoutParams.TYPE_PHONE; + } + DisplayMetrics displayMetrics = new DisplayMetrics(); + windowManager.getDefaultDisplay().getMetrics(displayMetrics); + layoutParams = new 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 | + WindowManager.LayoutParams.FLAG_FULLSCREEN | + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | + WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | + WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; + + layoutParams.gravity = Gravity.START | Gravity.TOP; + + Point screenSize = new Point(); + windowManager.getDefaultDisplay().getRealSize(screenSize); + layoutParams.width = screenSize.x; + layoutParams.height = screenSize.y; + } + + + public void showLockView() { + lockView.resetPinLockView(); + windowManager.addView(mView, layoutParams); + + } + + + public void unLock() { + try { + windowManager.removeView(mView); + } catch (Exception exception) { + + } + } + + +} diff --git a/app/src/main/java/com/tool/app/protectorpro/tools/MyThread.java b/app/src/main/java/com/tool/app/protectorpro/tools/MyThread.java new file mode 100644 index 0000000..da6e8b0 --- /dev/null +++ b/app/src/main/java/com/tool/app/protectorpro/tools/MyThread.java @@ -0,0 +1,35 @@ +package com.tool.app.protectorpro.tools; + +import android.os.Handler; +import android.os.Looper; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class MyThread { + + private static Handler mMainHandler; + + private static ExecutorService executorService; + + private static Handler getmMainHandler() { + if (mMainHandler == null) { + mMainHandler = new Handler(Looper.getMainLooper()); + } + return mMainHandler; + } + public static void runIO(Runnable task) { + getExecutorService().execute(task); + } + + private static ExecutorService getExecutorService() { + if (executorService == null) { + executorService = Executors.newSingleThreadExecutor(); + } + return executorService; + } + + public static void runUI(Runnable task) { + getmMainHandler().post(task); + } +} diff --git a/app/src/main/res/color/selector_text_color.xml b/app/src/main/res/color/selector_text_color.xml new file mode 100644 index 0000000..8422370 --- /dev/null +++ b/app/src/main/res/color/selector_text_color.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/back.xml b/app/src/main/res/drawable/back.xml new file mode 100644 index 0000000..dc8f6b1 --- /dev/null +++ b/app/src/main/res/drawable/back.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/bg_12_white.xml b/app/src/main/res/drawable/bg_12_white.xml new file mode 100644 index 0000000..0221b83 --- /dev/null +++ b/app/src/main/res/drawable/bg_12_white.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_30_green.xml b/app/src/main/res/drawable/bg_30_green.xml new file mode 100644 index 0000000..bc5f204 --- /dev/null +++ b/app/src/main/res/drawable/bg_30_green.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_36_4cd080.xml b/app/src/main/res/drawable/bg_36_4cd080.xml new file mode 100644 index 0000000..abcf023 --- /dev/null +++ b/app/src/main/res/drawable/bg_36_4cd080.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_36_b1dbff.xml b/app/src/main/res/drawable/bg_36_b1dbff.xml new file mode 100644 index 0000000..7ad006f --- /dev/null +++ b/app/src/main/res/drawable/bg_36_b1dbff.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_dia_step.xml b/app/src/main/res/drawable/bg_dia_step.xml new file mode 100644 index 0000000..2d53532 --- /dev/null +++ b/app/src/main/res/drawable/bg_dia_step.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_fragment.xml b/app/src/main/res/drawable/bg_fragment.xml new file mode 100644 index 0000000..5f61309 --- /dev/null +++ b/app/src/main/res/drawable/bg_fragment.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_sw.xml b/app/src/main/res/drawable/bg_sw.xml new file mode 100644 index 0000000..bbc42e5 --- /dev/null +++ b/app/src/main/res/drawable/bg_sw.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_tab_lock.xml b/app/src/main/res/drawable/bg_tab_lock.xml new file mode 100644 index 0000000..17b773e --- /dev/null +++ b/app/src/main/res/drawable/bg_tab_lock.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_tab_sys.xml b/app/src/main/res/drawable/bg_tab_sys.xml new file mode 100644 index 0000000..c0f35d7 --- /dev/null +++ b/app/src/main/res/drawable/bg_tab_sys.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_tab_three.xml b/app/src/main/res/drawable/bg_tab_three.xml new file mode 100644 index 0000000..2aa5817 --- /dev/null +++ b/app/src/main/res/drawable/bg_tab_three.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bottom_sheet_bg.xml b/app/src/main/res/drawable/bottom_sheet_bg.xml new file mode 100644 index 0000000..bf88b17 --- /dev/null +++ b/app/src/main/res/drawable/bottom_sheet_bg.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/drawable/delete.xml b/app/src/main/res/drawable/delete.xml new file mode 100644 index 0000000..5fd9940 --- /dev/null +++ b/app/src/main/res/drawable/delete.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/dia_choose.xml b/app/src/main/res/drawable/dia_choose.xml new file mode 100644 index 0000000..546a80b --- /dev/null +++ b/app/src/main/res/drawable/dia_choose.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/main_pwd.xml b/app/src/main/res/drawable/main_pwd.xml new file mode 100644 index 0000000..1945262 --- /dev/null +++ b/app/src/main/res/drawable/main_pwd.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable/oval_black.xml b/app/src/main/res/drawable/oval_black.xml new file mode 100644 index 0000000..48b0b70 --- /dev/null +++ b/app/src/main/res/drawable/oval_black.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_gray.xml b/app/src/main/res/drawable/oval_gray.xml new file mode 100644 index 0000000..82c89fc --- /dev/null +++ b/app/src/main/res/drawable/oval_gray.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_white.xml b/app/src/main/res/drawable/oval_white.xml new file mode 100644 index 0000000..522eb16 --- /dev/null +++ b/app/src/main/res/drawable/oval_white.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/pwd_bg.xml b/app/src/main/res/drawable/pwd_bg.xml new file mode 100644 index 0000000..4db3876 --- /dev/null +++ b/app/src/main/res/drawable/pwd_bg.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/tab_bg.xml b/app/src/main/res/drawable/tab_bg.xml new file mode 100644 index 0000000..0221b83 --- /dev/null +++ b/app/src/main/res/drawable/tab_bg.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/thumb_sw.xml b/app/src/main/res/drawable/thumb_sw.xml new file mode 100644 index 0000000..198a7fc --- /dev/null +++ b/app/src/main/res/drawable/thumb_sw.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/track_sw_green.xml b/app/src/main/res/drawable/track_sw_green.xml new file mode 100644 index 0000000..eb9915d --- /dev/null +++ b/app/src/main/res/drawable/track_sw_green.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/track_sw_white.xml b/app/src/main/res/drawable/track_sw_white.xml new file mode 100644 index 0000000..1c4da3d --- /dev/null +++ b/app/src/main/res/drawable/track_sw_white.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/font/inter.ttf b/app/src/main/res/font/inter.ttf new file mode 100644 index 0000000..2348f6b Binary files /dev/null and b/app/src/main/res/font/inter.ttf differ diff --git a/app/src/main/res/layout/activity_complete.xml b/app/src/main/res/layout/activity_complete.xml new file mode 100644 index 0000000..bbac82d --- /dev/null +++ b/app/src/main/res/layout/activity_complete.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main_layout.xml b/app/src/main/res/layout/activity_main_layout.xml new file mode 100644 index 0000000..974472c --- /dev/null +++ b/app/src/main/res/layout/activity_main_layout.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_set_pwd.xml b/app/src/main/res/layout/activity_set_pwd.xml new file mode 100644 index 0000000..ffb200c --- /dev/null +++ b/app/src/main/res/layout/activity_set_pwd.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_wel.xml b/app/src/main/res/layout/activity_wel.xml new file mode 100644 index 0000000..37b9d25 --- /dev/null +++ b/app/src/main/res/layout/activity_wel.xml @@ -0,0 +1,40 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/custom_float_snackbar.xml b/app/src/main/res/layout/custom_float_snackbar.xml new file mode 100644 index 0000000..b835b2a --- /dev/null +++ b/app/src/main/res/layout/custom_float_snackbar.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/app/src/main/res/layout/custom_password_input_view.xml b/app/src/main/res/layout/custom_password_input_view.xml new file mode 100644 index 0000000..1804caf --- /dev/null +++ b/app/src/main/res/layout/custom_password_input_view.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_permis.xml b/app/src/main/res/layout/dialog_permis.xml new file mode 100644 index 0000000..e2471f1 --- /dev/null +++ b/app/src/main/res/layout/dialog_permis.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/float_view.xml b/app/src/main/res/layout/float_view.xml new file mode 100644 index 0000000..d4dd306 --- /dev/null +++ b/app/src/main/res/layout/float_view.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_my.xml b/app/src/main/res/layout/fragment_my.xml new file mode 100644 index 0000000..1c137f9 --- /dev/null +++ b/app/src/main/res/layout/fragment_my.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_delete.xml b/app/src/main/res/layout/item_delete.xml new file mode 100644 index 0000000..e2fd72a --- /dev/null +++ b/app/src/main/res/layout/item_delete.xml @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_number.xml b/app/src/main/res/layout/item_number.xml new file mode 100644 index 0000000..248f0dc --- /dev/null +++ b/app/src/main/res/layout/item_number.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_systapp.xml b/app/src/main/res/layout/item_systapp.xml new file mode 100644 index 0000000..15f697b --- /dev/null +++ b/app/src/main/res/layout/item_systapp.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/set_bottom_sheet_layout.xml b/app/src/main/res/layout/set_bottom_sheet_layout.xml new file mode 100644 index 0000000..be7a2ad --- /dev/null +++ b/app/src/main/res/layout/set_bottom_sheet_layout.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/tab_view.xml b/app/src/main/res/layout/tab_view.xml new file mode 100644 index 0000000..1e72600 --- /dev/null +++ b/app/src/main/res/layout/tab_view.xml @@ -0,0 +1,30 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/float_snack_ic.png b/app/src/main/res/mipmap-xxxhdpi/float_snack_ic.png new file mode 100644 index 0000000..eb2ab1c Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/float_snack_ic.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_backspace.png b/app/src/main/res/mipmap-xxxhdpi/ic_backspace.png new file mode 100644 index 0000000..a1709f9 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_backspace.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_change.png b/app/src/main/res/mipmap-xxxhdpi/ic_change.png new file mode 100644 index 0000000..c5797a4 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_change.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_close.png b/app/src/main/res/mipmap-xxxhdpi/ic_close.png new file mode 100644 index 0000000..7877486 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_close.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_dia_step1.png b/app/src/main/res/mipmap-xxxhdpi/ic_dia_step1.png new file mode 100644 index 0000000..f276042 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_dia_step1.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_dia_step2.png b/app/src/main/res/mipmap-xxxhdpi/ic_dia_step2.png new file mode 100644 index 0000000..31facf6 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_dia_step2.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_next.png b/app/src/main/res/mipmap-xxxhdpi/ic_next.png new file mode 100644 index 0000000..f77e035 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_next.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_plaicy.png b/app/src/main/res/mipmap-xxxhdpi/ic_plaicy.png new file mode 100644 index 0000000..31f855a Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_plaicy.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/logo.png b/app/src/main/res/mipmap-xxxhdpi/logo.png new file mode 100644 index 0000000..8024a8e Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/logo.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/main_tab_lock_def.png b/app/src/main/res/mipmap-xxxhdpi/main_tab_lock_def.png new file mode 100644 index 0000000..7e967ad Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/main_tab_lock_def.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/main_tab_lock_en.png b/app/src/main/res/mipmap-xxxhdpi/main_tab_lock_en.png new file mode 100644 index 0000000..8c0b8f8 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/main_tab_lock_en.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/main_tab_sys_def.png b/app/src/main/res/mipmap-xxxhdpi/main_tab_sys_def.png new file mode 100644 index 0000000..1e2bace Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/main_tab_sys_def.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/main_tab_sys_en.png b/app/src/main/res/mipmap-xxxhdpi/main_tab_sys_en.png new file mode 100644 index 0000000..f0a0fad Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/main_tab_sys_en.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/main_tab_three_def.png b/app/src/main/res/mipmap-xxxhdpi/main_tab_three_def.png new file mode 100644 index 0000000..00e917f Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/main_tab_three_def.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/main_tab_three_en.png b/app/src/main/res/mipmap-xxxhdpi/main_tab_three_en.png new file mode 100644 index 0000000..a30a719 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/main_tab_three_en.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/track_sw_green_ic.png b/app/src/main/res/mipmap-xxxhdpi/track_sw_green_ic.png new file mode 100644 index 0000000..d73507d Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/track_sw_green_ic.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/track_sw_white_ic.png b/app/src/main/res/mipmap-xxxhdpi/track_sw_white_ic.png new file mode 100644 index 0000000..2df03b2 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/track_sw_white_ic.png differ diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..e2e7d52 --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..f53b0cf --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..c5215ff --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,27 @@ + + + #FFBB86FC + #FF6200EE + #FF018786 + #FF000000 + #FFFFFFFF + #FFF5F6F7 + #FF3700B3 + #FF0fa934 + #66000000 + #E5E5E5 + #FF72716F + #00000000 + #FFF4FAFF + #282638 + #FF0582EF + #FFB1DBFF + #1a8ee04e + #5aa2f1 + #FFFFFFFF + #1F1D2B + #FF3A3938 + #FF0582EF + #FF2A343D + + \ No newline at end of file diff --git a/app/src/main/res/values/dimmens.xml b/app/src/main/res/values/dimmens.xml new file mode 100644 index 0000000..f5e3f8b --- /dev/null +++ b/app/src/main/res/values/dimmens.xml @@ -0,0 +1,9 @@ + + + 16sp + 60dp + 32dp + 0dp + 8dp + 8dp + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..881e0b7 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,39 @@ + + AppLocker pro + Continue + Password + Rate Us + Share + Change Password + Confirm Password + Please enter your new 4-digit password + Please confirm your 4-digit password + Save + Your APP + Protect your privacy by locking apps with one click + locked: %s + Unlocked: %s + Congratulations, your password has been changed successfully + For normal use, please grant relevant permissions + permissions +For normal use App Lock, please grant the following + Usage access + Enables the system to capture and analyze your application\'s usage data. + Display on top of other apps + Enable that the application window or interface will be displayed on top of all other open applications. + come back home and enjoy the use of the features available for your problems + System App + Third APP + Lock APP + Set Passcode + Your initial password is required for first use + Back Home + please input complete + please sure input complete + Step 1 : Select + Step 2:Enabled + Please enter password + Settings + Change password + Privacy Policy + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..63374a0 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 0000000..fa0f996 --- /dev/null +++ b/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 0000000..9ee9997 --- /dev/null +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/test/java/com/tool/app/protectorpro/ExampleUnitTest.kt b/app/src/test/java/com/tool/app/protectorpro/ExampleUnitTest.kt new file mode 100644 index 0000000..2f9cb79 --- /dev/null +++ b/app/src/test/java/com/tool/app/protectorpro/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.tool.app.protectorpro + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit protectorpro, 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) + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..1bc1d16 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,5 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id("com.android.application") version "8.1.3" apply false + id("org.jetbrains.kotlin.android") version "1.9.0" apply false +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..3c5031e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true \ No newline at end of file diff --git a/gradle/applockpro1 b/gradle/applockpro1 new file mode 100644 index 0000000..7090055 Binary files /dev/null and b/gradle/applockpro1 differ diff --git a/gradle/jks_pass b/gradle/jks_pass new file mode 100644 index 0000000..6a859a4 --- /dev/null +++ b/gradle/jks_pass @@ -0,0 +1,5 @@ + + +alids:key_lockpro + +pass:12345600 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7bc2c1c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Mar 28 10:58:04 CST 2024 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..2e83b9d --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,19 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven (url ="https://jitpack.io" ) + } +} + +rootProject.name = "MyAppLock" +include(":app") + \ No newline at end of file