diff --git a/PermissionManager/.gitignore b/PermissionManager/.gitignore new file mode 100644 index 00000000..643d213c --- /dev/null +++ b/PermissionManager/.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/PermissionManager/app/.gitignore b/PermissionManager/app/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/PermissionManager/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/PermissionManager/app/build.gradle b/PermissionManager/app/build.gradle new file mode 100644 index 00000000..4a6c8874 --- /dev/null +++ b/PermissionManager/app/build.gradle @@ -0,0 +1,51 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + + defaultConfig { + applicationId "com.linux.permissionmanager" + minSdkVersion 26 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + cppFlags "-std=c++17" + abiFilters "arm64-v8a" //需要什么构架的so,就在这边添加即 + } + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + externalNativeBuild { + cmake { + path "src/main/cpp/CMakeLists.txt" + version "3.10.2" + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.3.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + testImplementation 'junit:junit:4.+' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' +} \ No newline at end of file diff --git a/PermissionManager/app/proguard-rules.pro b/PermissionManager/app/proguard-rules.pro new file mode 100644 index 00000000..64b4a059 --- /dev/null +++ b/PermissionManager/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# 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 \ No newline at end of file diff --git a/PermissionManager/app/src/androidTest/java/com/linux/permissionmanager/ExampleInstrumentedTest.java b/PermissionManager/app/src/androidTest/java/com/linux/permissionmanager/ExampleInstrumentedTest.java new file mode 100644 index 00000000..d7eca3a4 --- /dev/null +++ b/PermissionManager/app/src/androidTest/java/com/linux/permissionmanager/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.linux.permissionmanager; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.linux.permissionmanager", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/PermissionManager/app/src/main/AndroidManifest.xml b/PermissionManager/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..37686dd9 --- /dev/null +++ b/PermissionManager/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PermissionManager/app/src/main/cpp/CMakeLists.txt b/PermissionManager/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 00000000..42368b42 --- /dev/null +++ b/PermissionManager/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,53 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.10.2) + +# Declares and names the project. + +project("permissionmanager") + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. + +add_library( # Sets the name of the library. + root + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + ../../../../../testRoot/process64_inject.cpp + ../../../../../testRoot/adb64_helper.cpp + ../../../../../testRoot/ptrace_arm64_utils.cpp + ../../../../../testRoot/su_install_helper.cpp + ../../../../../testRoot/base64.cpp + root.cpp) + +# Searches for a specified prebuilt library and stores the path as a +# variable. Because CMake includes system libraries in the search path by +# default, you only need to specify the name of the public NDK library +# you want to add. CMake verifies that the library exists before +# completing its build. + +find_library( # Sets the name of the path variable. + log-lib + + # Specifies the name of the NDK library that + # you want CMake to locate. + log ) + +# Specifies libraries CMake should link to your target library. You +# can link multiple libraries, such as libraries you define in this +# build script, prebuilt third-party libraries, or system libraries. + +target_link_libraries( # Specifies the target library. + root + + # Links the target library to the log library + # included in the NDK. + ${log-lib} ) \ No newline at end of file diff --git a/PermissionManager/app/src/main/cpp/root.cpp b/PermissionManager/app/src/main/cpp/root.cpp new file mode 100644 index 00000000..178e5bd0 --- /dev/null +++ b/PermissionManager/app/src/main/cpp/root.cpp @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../../../../testRoot/testRoot.h" +#include "../../../../../testRoot/kernel_root_helper.h" +#include "../../../../../testRoot/process64_inject.h" +#include "../../../../../testRoot/adb64_helper.h" +#include "../../../../../testRoot/su_install_helper.h" + +using namespace std; +string getCapabilityInfo() +{ + __uid_t now_uid, now_euid, now_suid; + if (getresuid(&now_uid, &now_euid, &now_suid)) { + return "FAILED getresuid()"; + } + + + __gid_t now_gid, now_egid, now_sgid; + if (getresgid(&now_gid, &now_egid, &now_sgid)) { + return "FAILED getresgid()"; + } + + stringstream sstrCapInfo; + sstrCapInfo<< "now_uid="<pid = getpid(); + cap_header->version = _LINUX_CAPABILITY_VERSION_3; //_1、_2、_3 + + if (capget(cap_header, cap_data) < 0) { + return "FAILED capget()"; + // perror("FAILED capget()"); + //exit(1); + } + sstrCapInfo << "Cap data effective:"<<(uint64_t *) cap_data->effective<<", permitted:"<<(uint64_t *) cap_data->permitted<<", inheritable:"<<(uint64_t *) cap_data->inheritable<<"\n"; + + FILE * fp = popen("getenforce", "r"); + if (fp) + { + char cmd[512] = { 0 }; + fread(cmd, 1, sizeof(cmd), fp); + pclose(fp); + + sstrCapInfo<< "SELinux status: "<< cmd; + } + + return sstrCapInfo.str(); +} + +extern "C" JNIEXPORT jstring JNICALL +Java_com_linux_permissionmanager_MainActivity_getCapabilityInfo( + JNIEnv* env, + jobject /* this */) { + + return env->NewStringUTF(getCapabilityInfo().c_str()); +} + +extern "C" JNIEXPORT jint JNICALL +Java_com_linux_permissionmanager_MainActivity_getRoot( + JNIEnv* env, + jobject /* this */, + jlong rootKey) { + return get_root(rootKey); +} +extern "C" JNIEXPORT jint JNICALL +Java_com_linux_permissionmanager_MainActivity_disableSElinux( + JNIEnv* env, + jobject /* this */, + jlong rootKey) { + return safe_disable_selinux(rootKey); +} + +extern "C" JNIEXPORT jint JNICALL +Java_com_linux_permissionmanager_MainActivity_enableSElinux( + JNIEnv* env, + jobject /* this */, + jlong rootKey) { + return safe_enable_selinux(rootKey); +} + +extern "C" JNIEXPORT jstring JNICALL +Java_com_linux_permissionmanager_MainActivity_runNormalCmd( + JNIEnv* env, + jobject /* this */, + jlong rootKey, + jstring cmd) { + + const char *str1 = env->GetStringUTFChars(cmd, 0); + string strCmd= str1; + env->ReleaseStringUTFChars(cmd, str1); + + char szResult[0x1000] = {0}; + ssize_t ret = safe_run_normal_cmd(rootKey, strCmd.c_str(), szResult, sizeof(szResult)); + stringstream sstr; + sstr << "runRootCmd ret val:" << ret << ", result:" << szResult; + return env->NewStringUTF(sstr.str().c_str()); +} + +extern "C" JNIEXPORT jstring JNICALL +Java_com_linux_permissionmanager_MainActivity_runRootCmd( + JNIEnv* env, + jobject /* this */, + jlong rootKey, + jstring cmd) { + + const char *str1 = env->GetStringUTFChars(cmd, 0); + string strCmd= str1; + env->ReleaseStringUTFChars(cmd, str1); + + stringstream sstr; + char szResult[0x1000] = {0}; + ssize_t inject = safe_inject_adbd64_run_cmd_wrapper(rootKey, strCmd.c_str(), szResult, sizeof(szResult)); + //ssize_t inject = safe_inject_adbd64_run_cmd_wrapper(rootKey, strCmd.c_str(),NULL, 0); + sstr << "runRootCmd ret val:" << inject << ", result:" << szResult; + return env->NewStringUTF(sstr.str().c_str()); +} +extern "C" JNIEXPORT jstring JNICALL +Java_com_linux_permissionmanager_MainActivity_adbRoot( + JNIEnv* env, + jobject /* this */, + jlong rootKey) { + + stringstream sstr; + char szResult[0x1000] = {0}; + ssize_t inject = safe_inject_adbd64_run_cmd_wrapper(rootKey, "id", NULL, 0, false ,true ,false, false); + sstr << "adbRoot ret val:" << inject << ", result:" << szResult; + return env->NewStringUTF(sstr.str().c_str()); +} +extern "C" JNIEXPORT jstring JNICALL +Java_com_linux_permissionmanager_MainActivity_installSuTools( + JNIEnv* env, + jobject /* this */, + jlong rootKey, + jstring basePath, + jstring suToolsFilePath) { + + const char *str1 = env->GetStringUTFChars(basePath, 0); + string strBasePath= str1; + env->ReleaseStringUTFChars(basePath, str1); + + str1 = env->GetStringUTFChars(suToolsFilePath, 0); + string strSuFilePath= str1; + env->ReleaseStringUTFChars(suToolsFilePath, str1); + + stringstream sstr; + + //安装su工具套件 + std::string su_hidden_path; + int install_su_tools_ret = safe_install_su_tools(rootKey, strBasePath.c_str(), su_hidden_path); + sstr << "install_su_tools ret val:" << install_su_tools_ret<<", su_hidden_path:" << su_hidden_path << std::endl; + + if (install_su_tools_ret == -504) { + //需要补一下su文件的释放 + std::string tmpCmd = "cp "+strSuFilePath + " " + su_hidden_path+"/su"; + int cp_ret = safe_run_normal_cmd(rootKey, tmpCmd.c_str(), NULL, 0); + if(cp_ret != 0) { + sstr << "safe_run_normal_cmd cp_ret val:" <NewStringUTF(sstr.str().c_str()); + } + install_su_tools_ret = safe_install_su_tools(rootKey, strBasePath.c_str(), su_hidden_path); + sstr << "install_su_tools ret val:" << install_su_tools_ret<<", su_hidden_path:" << su_hidden_path << std::endl; + } + if (install_su_tools_ret != 0) { + return env->NewStringUTF(sstr.str().c_str()); + } + sstr << "installSuTools done."; + return env->NewStringUTF(sstr.str().c_str()); +} +extern "C" JNIEXPORT jstring JNICALL +Java_com_linux_permissionmanager_MainActivity_uninstallSuTools( + JNIEnv* env, + jobject /* this */, + jlong rootKey, + jstring basePath) { + + const char *str1 = env->GetStringUTFChars(basePath, 0); + string strBasePath= str1; + env->ReleaseStringUTFChars(basePath, str1); + + stringstream sstr; + + int uninstall_su_tools_ret = safe_uninstall_su_tools(rootKey, strBasePath.c_str()); + sstr << "uninstallSuTools ret val:" << uninstall_su_tools_ret << std::endl; + + if (uninstall_su_tools_ret != 0) { + return env->NewStringUTF(sstr.str().c_str()); + } + sstr << "uninstallSuTools done."; + return env->NewStringUTF(sstr.str().c_str()); +} +extern "C" JNIEXPORT jstring JNICALL +Java_com_linux_permissionmanager_MainActivity_autoSuEnvInject( + JNIEnv* env, + jobject /* this */, + jlong rootKey, + jstring targetProcessCmdline, + jstring basePath) { + + const char *str1 = env->GetStringUTFChars(targetProcessCmdline, 0); + string strTargetProcessCmdline= str1; + env->ReleaseStringUTFChars(targetProcessCmdline, str1); + + str1 = env->GetStringUTFChars(basePath, 0); + string strBasePath= str1; + env->ReleaseStringUTFChars(basePath, str1); + + stringstream sstr; + + //杀光所有历史进程 + std::vector vOut; + int find_all_cmdline_process_ret = safe_find_all_cmdline_process(rootKey, strTargetProcessCmdline.c_str(), vOut); + sstr << "find_all_cmdline_process ret val:"<< find_all_cmdline_process_ret<<", cnt:"<NewStringUTF(sstr.str().c_str()); + } + std::string kill_cmd; + for (pid_t t : vOut) { + kill_cmd += "kill -9 "; + kill_cmd += std::to_string(t); + kill_cmd += ";"; + } + int kill_ret = run_normal_cmd(rootKey, kill_cmd.c_str()); + sstr << "kill_ret ret val:"<< kill_ret << std::endl; + if (kill_ret != 0) { + return env->NewStringUTF(sstr.str().c_str()); + } + + //注入su环境变量到指定进程 + std::string su_hidden_path; + int install_su_tools_ret = safe_install_su_tools(rootKey, strBasePath.c_str(), su_hidden_path); + sstr << "install_su_tools ret val:" << install_su_tools_ret<<", su_hidden_path:" << su_hidden_path << std::endl; + if (install_su_tools_ret != 0) { + return env->NewStringUTF(sstr.str().c_str()); + } + + int pid = safe_wait_and_find_cmdline_process(rootKey, strTargetProcessCmdline.c_str()); + + sstr << "autoSuEnvInject("<< pid<<", " << su_hidden_path<<")" << std::endl; + ssize_t ret = safe_inject_process_env64_PATH_wrapper(rootKey, pid, su_hidden_path.c_str()); + sstr << "autoSuEnvInject ret val:" << ret << std::endl; + + if (ret != 0) { + return env->NewStringUTF(sstr.str().c_str()); + } + sstr << "autoSuEnvInject done."; + return env->NewStringUTF(sstr.str().c_str()); +} diff --git a/PermissionManager/app/src/main/java/com/linux/permissionmanager/Adapter/SelectAppRecyclerAdapter.java b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Adapter/SelectAppRecyclerAdapter.java new file mode 100644 index 00000000..c2a8ec6b --- /dev/null +++ b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Adapter/SelectAppRecyclerAdapter.java @@ -0,0 +1,110 @@ +package com.linux.permissionmanager.Adapter; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.PopupWindow; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.linux.permissionmanager.Model.SelectAppRecyclerItem; +import com.linux.permissionmanager.R; + +import java.util.List; + +public class SelectAppRecyclerAdapter extends RecyclerView.Adapter { + + + + public static class ViewHolder extends RecyclerView.ViewHolder { + public View v; + public ImageView select_app_icon; + public TextView select_app_text; + public TextView select_package_name; + // TODO Auto-generated method stub + public ViewHolder(View v) { + super(v); + this.v = v; + } + + } + + private int resourceId; + private List objects; + private PopupWindow popupWindow; + private Handler selectAppItemCallback; + public SelectAppRecyclerAdapter(Context context, int textViewResourceId, List objects, PopupWindow popupWindow, Handler selectAppItemCallback) { + this.resourceId = textViewResourceId; + this.objects = objects; + this. popupWindow = popupWindow; + this. selectAppItemCallback = selectAppItemCallback; + } + + + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View v =LayoutInflater.from(parent.getContext()).inflate(resourceId,parent,false); + SelectAppRecyclerAdapter.ViewHolder holder = new SelectAppRecyclerAdapter.ViewHolder(v); + + holder.select_app_icon = v.findViewById(R.id.select_app_icon); + holder.select_app_text=v.findViewById(R.id.select_app_text) ; + holder.select_package_name=v.findViewById(R.id.select_package_name) ; + return holder; + } + + + @Override + public void onBindViewHolder(@NonNull SelectAppRecyclerAdapter.ViewHolder holder, int position) { + SelectAppRecyclerItem appItem=objects.get(position); //获取当前项的实例 + + //图标+进程PID+名字+内存 + holder.select_app_icon.setImageDrawable(appItem.getIcon()); + String showText=""+appItem.getShowName() +" " + +" "+" ("+appItem.getPackageName()+")"+""; + + holder.select_app_text.setText(Html.fromHtml(showText)); + holder.select_package_name.setText(appItem.getPackageName()); + + //item被点击 + holder.v.setOnClickListener(new ClickRecyclerItemListener(appItem)); + } + + + @Override + public int getItemCount() { + return objects.size(); + } + + @Override + public int getItemViewType(int position) { + return position; + } + + + class ClickRecyclerItemListener implements View.OnClickListener { + SelectAppRecyclerItem appItem; + public ClickRecyclerItemListener( SelectAppRecyclerItem appItem){ + this.appItem =appItem; + } + @Override + public void onClick(View v) { + popupWindow.dismiss(); + Message msg = new Message(); + msg.obj = (SelectAppRecyclerItem)appItem; + selectAppItemCallback.sendMessage(msg); + } + } + + + + +} diff --git a/PermissionManager/app/src/main/java/com/linux/permissionmanager/MainActivity.java b/PermissionManager/app/src/main/java/com/linux/permissionmanager/MainActivity.java new file mode 100644 index 00000000..dcddce02 --- /dev/null +++ b/PermissionManager/app/src/main/java/com/linux/permissionmanager/MainActivity.java @@ -0,0 +1,540 @@ +package com.linux.permissionmanager; + +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.PopupWindow; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.linux.permissionmanager.Adapter.SelectAppRecyclerAdapter; +import com.linux.permissionmanager.Model.PopupWindowOnTouchClose; +import com.linux.permissionmanager.Model.SelectAppRecyclerItem; +import com.linux.permissionmanager.Utils.ScreenInfoUtils; +import com.linux.permissionmanager.Utils.UsbDebugSwitchHelper; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class MainActivity extends AppCompatActivity { + + private long rootKey = 0x7F6766F8; + + private String suBasePath = "/data/local/tmp"; + + //保存的本地配置信息 + private SharedPreferences m_shareSave; + private ProgressDialog m_loadingDlg = null; + + // Used to load the 'native-lib' library on application startup. + static { + System.loadLibrary("root"); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + + m_shareSave = getSharedPreferences("zhcs", Context.MODE_PRIVATE); + try { + rootKey = m_shareSave.getLong("rootKey", rootKey); + } catch (Exception e) { + } + + //验证用户的KEY + final EditText inputKey = new EditText(MainActivity.this); + inputKey.setText(Long.toHexString(rootKey)); + inputKey.setSelection(inputKey.length(), 0); + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setCancelable(false); + builder.setTitle("请输入ROOT权限的KEY").setIcon(android.R.drawable.ic_dialog_info).setView(inputKey) + .setPositiveButton("确定", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + rootKey = Long.valueOf(inputKey.getText().toString(), 16); + //数值保存到本地 + SharedPreferences.Editor mEdit = m_shareSave.edit(); + mEdit.putLong("rootKey", rootKey); + mEdit.commit(); + } + + ; + }); + builder.show(); + + + Button show_myself_info_btn = findViewById(R.id.show_myself_info_btn); + show_myself_info_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showConsoleMsg(getCapabilityInfo()); + } + }); + + Button get_root_btn = findViewById(R.id.get_root_btn); + get_root_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int ret = getRoot(rootKey); + showConsoleMsg("getRoot: " + ret); + } + }); + + Button disable_selinux_btn = findViewById(R.id.disable_selinux_btn); + disable_selinux_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int ret = disableSElinux(rootKey); + showConsoleMsg("disableSElinux: " + ret); + } + }); + + Button enable_selinux_btn = findViewById(R.id.enable_selinux_btn); + enable_selinux_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int ret = enableSElinux(rootKey); + showConsoleMsg("enableSElinux: " + ret); + } + }); + + Button run_normal_cmd_btn = findViewById(R.id.run_normal_cmd_btn); + run_normal_cmd_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + final EditText inputCMD = new EditText(MainActivity.this); + inputCMD.setText("id"); + inputCMD.setSelection(inputCMD.length(), 0); + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setTitle("输入普通命令").setIcon(android.R.drawable.ic_dialog_info).setView(inputCMD) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + String text = inputCMD.getText().toString(); + showConsoleMsg(text + "\n" + runNormalCmd(rootKey, text)); + } + + ; + }); + builder.show(); + + } + }); + Button run_root_cmd_btn = findViewById(R.id.run_root_cmd_btn); + run_root_cmd_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + if (!guideOpenUsbDebugSwitch()) { + return; + } + final EditText inputCMD = new EditText(MainActivity.this); + inputCMD.setText("id"); + inputCMD.setSelection(inputCMD.length(), 0); + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setTitle("输入ROOT命令").setIcon(android.R.drawable.ic_dialog_info).setView(inputCMD) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + String text = inputCMD.getText().toString(); + showConsoleMsg(text + "\n" + runRootCmd(rootKey, text)); + } + }); + builder.show(); + + } + }); + Button adb_root_btn = findViewById(R.id.adb_root_btn); + adb_root_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + if (!guideOpenUsbDebugSwitch()) { + return; + } + showConsoleMsg(adbRoot(rootKey)); + } + }); + + Button su_env_inject_btn = findViewById(R.id.su_env_inject_btn); + su_env_inject_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!guideOpenUsbDebugSwitch()) { + return; + } + //1.获取su工具文件路径 + String suToolsFilePath = WirteSuToolsFilePath(MainActivity.this); + showConsoleMsg(suToolsFilePath); + + //2.安装su工具 + String insRet = installSuTools(rootKey, suBasePath, suToolsFilePath); + showConsoleMsg(insRet); + if(insRet.indexOf("installSuTools done.") == -1) { + return; + } + + //3.选择APP进程 + showSelectAppWindow(); + + } + }); + + Button clean_su_btn = findViewById(R.id.clean_su_btn); + clean_su_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showConsoleMsg(uninstallSuTools(rootKey,suBasePath)); + } + }); + + Button copy_info_btn = findViewById(R.id.copy_info_btn); + copy_info_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + copyConsoleMsg(); + Toast.makeText(v.getContext(), "复制成功", Toast.LENGTH_SHORT).show(); + + } + }); + Button clean_info_btn = findViewById(R.id.clean_info_btn); + clean_info_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + cleanConsoleMsg(); + } + }); + } + + public void showConsoleMsg(String msg) { + EditText console_edit = findViewById(R.id.console_edit); + StringBuffer txt = new StringBuffer(); + txt.append(console_edit.getText().toString()); + if (txt.length() != 0) { + txt.append("\n"); + } + txt.append(msg); + txt.append("\n"); + console_edit.setText(txt.toString()); + console_edit.setSelection(txt.length()); + } + + public void cleanConsoleMsg() { + EditText console_edit = findViewById(R.id.console_edit); + console_edit.setText(""); + } + + public void copyConsoleMsg() { + EditText console_edit = findViewById(R.id.console_edit); + //获取剪贴板管理器: + ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + // 创建普通字符型ClipData + ClipData mClipData = ClipData.newPlainText("Label", console_edit.getText()); + // 将ClipData内容放到系统剪贴板里。 + cm.setPrimaryClip(mClipData); + + } + + public boolean guideOpenUsbDebugSwitch() { + //检查USB调试开关是否打开 + if (!UsbDebugSwitchHelper.checkUsbDebugSwitch(MainActivity.this)) { + + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this) + .setTitle("提示") + .setCancelable(false) + .setMessage("请先到开发者选项页面里打开【USB调试】开关(提示:在手机关于页面里连续点击系统版本号可启用开发者选项页面)") + .setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + dialog.dismiss(); + UsbDebugSwitchHelper.startDevelopmentActivity(MainActivity.this); //转到开发者页面 + } + }) + .setNegativeButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + UsbDebugSwitchHelper.startDevelopmentActivity(MainActivity.this); //转到开发者页面 + + } + }); + AlertDialog dialog = builder.create(); + dialog.show(); + dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(Color.BLACK); + + return false; + } + return true; + } + + public boolean guideCloseUsbDebugSwitch() { + //检查USB调试开关是否打开 + if (UsbDebugSwitchHelper.checkUsbDebugSwitch(MainActivity.this)) { + + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this) + .setTitle("提示") + .setCancelable(false) + .setMessage("请先到开发者选项页面里关闭【USB调试】开关") + .setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + dialog.dismiss(); + UsbDebugSwitchHelper.startDevelopmentActivity(MainActivity.this); //转到开发者页面 + } + }) + .setNegativeButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + UsbDebugSwitchHelper.startDevelopmentActivity(MainActivity.this); //转到开发者页面 + + } + }); + AlertDialog dialog = builder.create(); + dialog.show(); + dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(Color.BLACK); + return false; + } + return true; + } + + + Handler selectAppItemCallback = new Handler() { + @Override + public void handleMessage(@NonNull Message msg) { + + SelectAppRecyclerItem appItem = (SelectAppRecyclerItem) msg.obj; + + if (m_loadingDlg == null) { + m_loadingDlg = new ProgressDialog(MainActivity.this); + m_loadingDlg.setCancelable(false); + } + m_loadingDlg.setTitle(""); + m_loadingDlg.setMessage("请现在手动启动APP [" + appItem.getShowName() + "]"); + m_loadingDlg.show(); + + new Thread() { + public void run() { + String ret = autoSuEnvInject(rootKey, appItem.getPackageName(), suBasePath); + runOnUiThread(new Runnable() { + public void run() { + showConsoleMsg(ret); + m_loadingDlg.cancel(); + + if(ret.indexOf("autoSuEnvInject done.")!= -1) { + //弹个提示,通知一下成功了 + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this) + .setCancelable(false) + .setTitle("提示") + .setIcon(appItem.getIcon()) + .setMessage("已经授予ROOT权限到APP [" + appItem.getShowName() + "]") + .setNegativeButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + AlertDialog dialog = builder.create(); + dialog.show(); + dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(Color.BLACK); + } + + + + + } + }); + } + }.start(); + super.handleMessage(msg); + } + }; + + //显示选择应用程序窗口 + public void showSelectAppWindow() { + final PopupWindow popupWindow = new PopupWindow(this); + + View view = View.inflate(this, R.layout.select_app_wnd, null); + popupWindow.setContentView(view); + + popupWindow.setHeight(ViewGroup.LayoutParams.MATCH_PARENT); + popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); + popupWindow.setBackgroundDrawable(new ColorDrawable(0x9B000000)); //阴影半透明 + popupWindow.setOutsideTouchable(true); + popupWindow.setFocusable(true); + popupWindow.setTouchable(true); + + //全屏 + View parent = View.inflate(MainActivity.this, R.layout.activity_main, null); + popupWindow.showAtLocation(parent, Gravity.NO_GRAVITY, 0, 0); + popupWindow.showAsDropDown(parent, 0, 0); + + popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { + @Override + public void onDismiss() { //窗口即将关闭 + + } + }); + + //设置中心布局大小 + final int screenWidth = ScreenInfoUtils.getRealWidth(this); + final int screenHeight = ScreenInfoUtils.getRealHeight(this); + + final double centerWidth = ((double) screenWidth) * 0.80; + final double centerHeight = ((double) screenHeight) * 0.90; + + LinearLayout center_layout = (LinearLayout) view.findViewById(R.id.center_layout); + android.view.ViewGroup.LayoutParams lp = center_layout.getLayoutParams(); + lp.width = (int) centerWidth; + lp.height = (int) centerHeight; + + //点击阴影部分可关闭窗口 + popupWindow.setTouchInterceptor(new PopupWindowOnTouchClose(popupWindow, + screenWidth, screenHeight, (int) centerWidth, (int) centerHeight)); + + //显示APP列表 + List appList = new ArrayList<>(); + + //获取已安装的APK列表 + List packages = getPackageManager().getInstalledPackages(0); + + //先判断cmdline与包名是否完全相同 + for (int i = 0; i < packages.size(); i++) { + PackageInfo packageInfo = packages.get(i); + + if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + //系统应用 + continue; + } + String showName = packageInfo.applicationInfo.loadLabel(getPackageManager()).toString(); + + Drawable icon = packageInfo.applicationInfo.loadIcon(getPackageManager()); + + String packageName = packageInfo.applicationInfo.packageName; + if(packageName.equals(getPackageName())){ + //不显示自己 + continue; + } + //加入到显示APP列表 + appList.add(new SelectAppRecyclerItem( + icon, + showName, + packageName)); + } + for (int i = 0; i < packages.size(); i++) { + PackageInfo packageInfo = packages.get(i); + + if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + //非系统应用 + continue; + } + + String showName = packageInfo.applicationInfo.loadLabel(getPackageManager()).toString(); + + Drawable icon = packageInfo.applicationInfo.loadIcon(getPackageManager()); + + String packageName = packageInfo.applicationInfo.packageName; + + //加入到显示APP列表 + appList.add(new SelectAppRecyclerItem( + icon, + showName, + packageName)); + } + + SelectAppRecyclerAdapter adapter = new SelectAppRecyclerAdapter( + MainActivity.this, R.layout.select_app_recycler_item, appList, popupWindow, selectAppItemCallback); + + RecyclerView select_app_recycler_view = (RecyclerView) view.findViewById(R.id.select_app_recycler_view); + // 设置布局管理器 + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + select_app_recycler_view.setLayoutManager(linearLayoutManager); + select_app_recycler_view.setAdapter(adapter); + + } + + public static String WirteSuToolsFilePath(Context context) { + String suFileName = "su"; + String suFilePath = ""; + try { + suFilePath = context.getFilesDir().getPath() + "/" + suFileName; + File file = new File(suFilePath); + if (!file.exists()) { + if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); + file.createNewFile(); + } + if (file.exists()) { + InputStream inputStream = context.getAssets().open(suFileName); + FileOutputStream outputStream = new FileOutputStream(file); + byte[] content = new byte[1024]; + while (inputStream.read(content) > 0) { + outputStream.write(content); + } + inputStream.close(); + outputStream.flush(); + outputStream.close(); + } + } catch (Exception e) { + } + return suFilePath; + } + + + public native String getCapabilityInfo(); + + public native int getRoot(long rootKey); + + public native int disableSElinux(long rootKey); + + public native int enableSElinux(long rootKey); + + public native String runNormalCmd(long rootKey, String cmd); + + public native String runRootCmd(long rootKey, String cmd); + + public native String adbRoot(long rootKey); + + public native String installSuTools(long rootKey, String basePath, String suToolsFilePath); + + public native String uninstallSuTools(long rootKey, String basePath); + + public native String autoSuEnvInject(long rootKey, String targetProcessCmdline, String basePath); +} \ No newline at end of file diff --git a/PermissionManager/app/src/main/java/com/linux/permissionmanager/Model/PopupWindowOnTouchClose.java b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Model/PopupWindowOnTouchClose.java new file mode 100644 index 00000000..3856843a --- /dev/null +++ b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Model/PopupWindowOnTouchClose.java @@ -0,0 +1,48 @@ +package com.linux.permissionmanager.Model; + +import android.view.MotionEvent; +import android.view.View; +import android.widget.PopupWindow; + +public class PopupWindowOnTouchClose implements View.OnTouchListener { + private boolean lastVailedDown = true; + private int screenWidth, screenHeight, centerWidth, centerHeight; + private PopupWindow popupWindow; + + public PopupWindowOnTouchClose(PopupWindow popupWindow, int screenWidth, int screenHeight, int centerWidth, int centerHeight) { + this.popupWindow = popupWindow; + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + this.centerWidth = centerWidth; + this.centerHeight = centerHeight; + } + + private boolean isValiedRegion(View v, MotionEvent event) { + int x = (int) event.getX(); + int y = (int) event.getY(); + double wndLeft = (screenWidth - centerWidth) / 2; + double wndTop = (screenHeight - centerHeight) / 2; + if (x < wndLeft || x > wndLeft + centerWidth || y < wndTop || y > wndTop + centerHeight) { + return false; + } + return true; + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + + if (event.getAction() == MotionEvent.ACTION_DOWN) { + lastVailedDown = isValiedRegion(v, event); + } else if (event.getAction() == MotionEvent.ACTION_UP) { + if (!lastVailedDown) { + if (!isValiedRegion(v, event)) { + popupWindow.dismiss(); + } + } + } + return false; + } +} + + + diff --git a/PermissionManager/app/src/main/java/com/linux/permissionmanager/Model/SelectAppRecyclerItem.java b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Model/SelectAppRecyclerItem.java new file mode 100644 index 00000000..f754bbd6 --- /dev/null +++ b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Model/SelectAppRecyclerItem.java @@ -0,0 +1,40 @@ +package com.linux.permissionmanager.Model; + +import android.graphics.drawable.Drawable; + +public class SelectAppRecyclerItem { + private Drawable icon=null; + private String showName; + private String packageName; + + public SelectAppRecyclerItem(Drawable icon, String showName, String packageName){ + this.icon=icon; + this.showName = showName; + this.packageName = packageName; + } + + public Drawable getIcon() { + return icon; + } + + public void setIcon(Drawable icon) { + this.icon = icon; + } + + public String getShowName() { + return showName; + } + + public void setShowName(String showName) { + this.showName = showName; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + +} diff --git a/PermissionManager/app/src/main/java/com/linux/permissionmanager/UsbDebugSwitchHelper.java b/PermissionManager/app/src/main/java/com/linux/permissionmanager/UsbDebugSwitchHelper.java new file mode 100644 index 00000000..53e1f489 --- /dev/null +++ b/PermissionManager/app/src/main/java/com/linux/permissionmanager/UsbDebugSwitchHelper.java @@ -0,0 +1,41 @@ +package com.linux.permissionmanager; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.provider.Settings; + +public class UsbDebugSwitchHelper { + public static boolean checkUsbDebugSwitch(Context ctx) { + //检查USB调试是否被打开 + boolean enableAdb = (Settings.Secure.getInt(ctx.getContentResolver(), Settings.Secure.ADB_ENABLED, 0) > 0);//判断adb调试模式是否打开 + return enableAdb; + } + + /** + * 打开开发者模式界面 + */ + public static void startDevelopmentActivity(Context ctx) { + try { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); + ctx.startActivity(intent); + } catch (Exception e) { + try { + ComponentName componentName = new ComponentName("com.android.settings", "com.android.settings.DevelopmentSettings"); + Intent intent = new Intent(); + intent.setComponent(componentName); + intent.setAction("android.intent.action.View"); + ctx.startActivity(intent); + } catch (Exception e1) { + try { + Intent intent = new Intent("com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS");//部分小米手机采用这种方式跳转 + ctx.startActivity(intent); + } catch (Exception e2) { + + } + + } + } + } + +} diff --git a/PermissionManager/app/src/main/java/com/linux/permissionmanager/Utils/ScreenInfoUtils.java b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Utils/ScreenInfoUtils.java new file mode 100644 index 00000000..a4b29642 --- /dev/null +++ b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Utils/ScreenInfoUtils.java @@ -0,0 +1,173 @@ +package com.linux.permissionmanager.Utils; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Resources; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; +import android.view.Display; +import android.view.WindowManager; + +/** + * Get Screen Information Utils + * + * @author yh + * @date 2018/12/18. + */ +public class ScreenInfoUtils { + + private static final String TAG = "ScreenInfoUtils"; + + /** + * Get Screen Width + */ + public static int getScreenWidth(Context context) { + return getDisplayMetrics(context).widthPixels; + } + + /** + * Get Screen Height + */ + public static int getScreenHeight(Context context) { + return getDisplayMetrics(context).heightPixels; + } + + + /** + * Get Screen Real Height + * + * @param context Context + * @return Real Height + */ + public static int getRealHeight(Context context) { + Display display = getDisplay(context); + if (display == null) { + return 0; + } + DisplayMetrics dm = new DisplayMetrics(); + display.getRealMetrics(dm); + return dm.heightPixels; + } + + /** + * Get Screen Real Width + * + * @param context Context + * @return Real Width + */ + public static int getRealWidth(Context context) { + Display display = getDisplay(context); + if (display == null) { + return 0; + } + DisplayMetrics dm = new DisplayMetrics(); + display.getRealMetrics(dm); + return dm.widthPixels; + } + + /** + * Get StatusBar Height + */ + public static int getStatusBarHeight(Context mContext) { + int resourceId = mContext.getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + return mContext.getResources().getDimensionPixelSize(resourceId); + } + return 0; + } + + /** + * Get ActionBar Height + */ + public static int getActionBarHeight(Context mContext) { + TypedValue tv = new TypedValue(); + if (mContext.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { + return TypedValue.complexToDimensionPixelSize(tv.data, mContext.getResources().getDisplayMetrics()); + } + return 0; + } + + /** + * Get NavigationBar Height + */ + public static int getNavigationBarHeight(Context mContext) { + Resources resources = mContext.getResources(); + int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (resourceId > 0) { + return resources.getDimensionPixelSize(resourceId); + } + return 0; + } + + /** + * Get Density + */ + private static float getDensity(Context context) { + return getDisplayMetrics(context).density; + } + + /** + * Get Dpi + */ + private static int getDpi(Context context) { + return getDisplayMetrics(context).densityDpi; + } + + /** + * Get Display + * + * @param context Context for get WindowManager + * @return Display + */ + private static Display getDisplay(Context context) { + WindowManager wm; + if (context instanceof Activity) { + Activity activity = (Activity) context; + wm = activity.getWindowManager(); + } else { + wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + } + if (wm != null) { + return wm.getDefaultDisplay(); + } + return null; + } + + /** + * Get DisplayMetrics + * + * @param context Context for get Resources + * @return DisplayMetrics + */ + private static DisplayMetrics getDisplayMetrics(Context context) { + return context.getResources().getDisplayMetrics(); + } + + + /** + * Get ScreenInfo + */ + private static String getScreenInfo(Context context) { + return " \n" + + "--------ScreenInfo--------" + "\n" + + "Screen Width : " + getScreenWidth(context) + "px\n" + + "Screen RealWidth :" + getRealWidth(context) + "px\n" + + "Screen Height: " + getScreenHeight(context) + "px\n" + + "Screen RealHeight: " + getRealHeight(context) + "px\n" + + "Screen StatusBar Height: " + getStatusBarHeight(context)+ "px\n" + + "Screen ActionBar Height: " + getActionBarHeight(context)+ "px\n" + + "Screen NavigationBar Height: " + getNavigationBarHeight(context)+ "px\n" + + "Screen Dpi: " + getDpi(context) + "\n" + + "Screen Density: " + getDensity(context) + "\n" + + "--------------------------"; + } + + + /** + * Print screenInfo to logcat + */ + public static void printScreenInfo(Context context) { + Log.d(TAG, getScreenInfo(context)); + } +} diff --git a/PermissionManager/app/src/main/java/com/linux/permissionmanager/Utils/UsbDebugSwitchHelper.java b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Utils/UsbDebugSwitchHelper.java new file mode 100644 index 00000000..3d9192bb --- /dev/null +++ b/PermissionManager/app/src/main/java/com/linux/permissionmanager/Utils/UsbDebugSwitchHelper.java @@ -0,0 +1,41 @@ +package com.linux.permissionmanager.Utils; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.provider.Settings; + +public class UsbDebugSwitchHelper { + public static boolean checkUsbDebugSwitch(Context ctx) { + //检查USB调试是否被打开 + boolean enableAdb = (Settings.Secure.getInt(ctx.getContentResolver(), Settings.Secure.ADB_ENABLED, 0) > 0);//判断adb调试模式是否打开 + return enableAdb; + } + + /** + * 打开开发者模式界面 + */ + public static void startDevelopmentActivity(Context ctx) { + try { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); + ctx.startActivity(intent); + } catch (Exception e) { + try { + ComponentName componentName = new ComponentName("com.android.settings", "com.android.settings.DevelopmentSettings"); + Intent intent = new Intent(); + intent.setComponent(componentName); + intent.setAction("android.intent.action.View"); + ctx.startActivity(intent); + } catch (Exception e1) { + try { + Intent intent = new Intent("com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS");//部分小米手机采用这种方式跳转 + ctx.startActivity(intent); + } catch (Exception e2) { + + } + + } + } + } + +} diff --git a/PermissionManager/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/PermissionManager/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000..cc14f035 --- /dev/null +++ b/PermissionManager/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/PermissionManager/app/src/main/res/drawable/ic_launcher_background.xml b/PermissionManager/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..a4f78de5 --- /dev/null +++ b/PermissionManager/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PermissionManager/app/src/main/res/drawable/line.xml b/PermissionManager/app/src/main/res/drawable/line.xml new file mode 100644 index 00000000..edc8c384 --- /dev/null +++ b/PermissionManager/app/src/main/res/drawable/line.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/PermissionManager/app/src/main/res/drawable/line_drawable.xml b/PermissionManager/app/src/main/res/drawable/line_drawable.xml new file mode 100644 index 00000000..963faca1 --- /dev/null +++ b/PermissionManager/app/src/main/res/drawable/line_drawable.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/PermissionManager/app/src/main/res/drawable/ripple_grey.xml b/PermissionManager/app/src/main/res/drawable/ripple_grey.xml new file mode 100644 index 00000000..9fe6ea1b --- /dev/null +++ b/PermissionManager/app/src/main/res/drawable/ripple_grey.xml @@ -0,0 +1,6 @@ + +//点击时波纹的颜色 + //未点击时控件的背景(可以是图片,可以是颜色,也可以是drawable里的xml背景(比如圆角)) + \ No newline at end of file diff --git a/PermissionManager/app/src/main/res/drawable/shape_wnd_grey_corner.xml b/PermissionManager/app/src/main/res/drawable/shape_wnd_grey_corner.xml new file mode 100644 index 00000000..1e51d694 --- /dev/null +++ b/PermissionManager/app/src/main/res/drawable/shape_wnd_grey_corner.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/PermissionManager/app/src/main/res/drawable/thumb.xml b/PermissionManager/app/src/main/res/drawable/thumb.xml new file mode 100644 index 00000000..347480a8 --- /dev/null +++ b/PermissionManager/app/src/main/res/drawable/thumb.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/PermissionManager/app/src/main/res/drawable/thumb_drawable.xml b/PermissionManager/app/src/main/res/drawable/thumb_drawable.xml new file mode 100644 index 00000000..f32eb927 --- /dev/null +++ b/PermissionManager/app/src/main/res/drawable/thumb_drawable.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/PermissionManager/app/src/main/res/layout/activity_main.xml b/PermissionManager/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..8a71afb0 --- /dev/null +++ b/PermissionManager/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + +