diff --git a/app/build.gradle b/app/build.gradle index 0bff609..6c18edb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { applicationId "com.uiui.aios" minSdkVersion 24 targetSdkVersion 29 - versionCode 42 - versionName "5.1" + versionCode 43 + versionName "5.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/com/uiui/aios/activity/main/MainActivity.java b/app/src/main/java/com/uiui/aios/activity/main/MainActivity.java index dac6897..a2f713d 100644 --- a/app/src/main/java/com/uiui/aios/activity/main/MainActivity.java +++ b/app/src/main/java/com/uiui/aios/activity/main/MainActivity.java @@ -38,6 +38,7 @@ import com.uiui.aios.fragment.SecondFragment; import com.uiui.aios.service.NotificationService; import com.uiui.aios.utils.ApkUtils; import com.uiui.aios.utils.AppUsedTimeUtils; +import com.uiui.aios.utils.LauncherUtils; import com.uiui.aios.utils.ToastUtil; import com.uiui.aios.view.ScaleCircleNavigator; @@ -52,7 +53,7 @@ import butterknife.BindView; import butterknife.ButterKnife; public class MainActivity extends BaseActivity implements MainContact.MainView { - private static String TAG = MainActivity.class.getSimpleName(); + private static final String TAG = MainActivity.class.getSimpleName(); private MainPresenter mMainPresenter; @BindView(R.id.viewPager) @@ -84,7 +85,9 @@ public class MainActivity extends BaseActivity implements MainContact.MainView { mMainPresenter.attachView(this); mMainPresenter.setLifecycle(lifecycleSubject); + if (BuildConfig.DEBUG) { + Log.e(TAG, "initView: " + this.getClass().getName()); // SystemClock.setCurrentTimeMillis(1662123600000L);//09-02 // SystemClock.setCurrentTimeMillis(1662210000000L);//09-03 } @@ -297,6 +300,9 @@ public class MainActivity extends BaseActivity implements MainContact.MainView { ToastUtil.show("请授予\"" + getString(R.string.app_name) + "\"使用通知权"); gotoNotificationAccessSetting(this); } + if (!LauncherUtils.isDefaultHome(this)) { + LauncherUtils.setDefaultDesktop(this, BuildConfig.APPLICATION_ID, this.getClass().getName()); + } addData(); mMainPresenter.sendRunningInfo(); mMainPresenter.getAdminSnSetting(); diff --git a/app/src/main/java/com/uiui/aios/bean/DesktopIcon.java b/app/src/main/java/com/uiui/aios/bean/DesktopIcon.java index 6262eee..42061ed 100644 --- a/app/src/main/java/com/uiui/aios/bean/DesktopIcon.java +++ b/app/src/main/java/com/uiui/aios/bean/DesktopIcon.java @@ -17,7 +17,7 @@ public class DesktopIcon implements Serializable , Parcelable { String lable; int position; - private DesktopIcon() { + public DesktopIcon() { } diff --git a/app/src/main/java/com/uiui/aios/dialog/PasswordDialog.java b/app/src/main/java/com/uiui/aios/dialog/PasswordDialog.java new file mode 100644 index 0000000..aba1a93 --- /dev/null +++ b/app/src/main/java/com/uiui/aios/dialog/PasswordDialog.java @@ -0,0 +1,273 @@ +package com.uiui.aios.dialog; + + +import android.content.Context; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.appcompat.app.AlertDialog; + +import com.uiui.aios.R; + + +/** + * description:自定义dialog + */ + +public class PasswordDialog extends AlertDialog { + /** + * 显示的图片 + */ + private ImageView imageIv; + + /** + * 显示的标题 + */ + private TextView titleTv; + + /** + * 显示的消息 + */ + private EditText messageTv; + + /** + * 确认和取消按钮 + */ + private TextView positiveBn; + private TextView negtiveBn; + + /** + * 按钮之间的分割线 + */ +// private View columnLineView; + + private Context mContext; + + public PasswordDialog(Context context) { + super(context, R.style.CustomDialog); + this.mContext = context; + } + + /** + * 都是内容数据 + */ + private String message; + private String title; + private String positive, negtive; + private int imageResId = -1; + + /** + * 底部是否只有一个按钮 + */ + private boolean isSingle = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.password_dialog); + //按空白处不能取消动画 + setCanceledOnTouchOutside(false); + //初始化界面控件 + initView(); + //初始化界面数据 + refreshView(); + //初始化界面控件的事件 + initEvent(); + } + + /** + * 初始化界面的确定和取消监听器 + */ + private void initEvent() { + //设置确定按钮被点击后,向外界提供监听 + positiveBn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onClickBottomListener != null) { + onClickBottomListener.onPositiveClick(); + } + } + }); + //设置取消按钮被点击后,向外界提供监听 + negtiveBn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onClickBottomListener != null) { + onClickBottomListener.onNegtiveClick(); + } + } + }); + } + + /** + * 初始化界面控件的显示数据 + */ + private void refreshView() { + //如果用户自定了title和message + if (!TextUtils.isEmpty(title)) { + titleTv.setText(title); + titleTv.setVisibility(View.VISIBLE); + } else { + titleTv.setVisibility(View.GONE); + } + if (!TextUtils.isEmpty(message)) { + messageTv.setText(message); + } + //如果设置按钮的文字 + if (!TextUtils.isEmpty(positive)) { + positiveBn.setText(positive); + } else { + positiveBn.setText("确定"); + } + if (!TextUtils.isEmpty(negtive)) { + negtiveBn.setText(negtive); + } else { + negtiveBn.setText("取消"); + } + + if (imageResId != -1) { + imageIv.setImageResource(imageResId); + imageIv.setVisibility(View.VISIBLE); + } else { + imageIv.setVisibility(View.GONE); + } + /** + * 只显示一个按钮的时候隐藏取消按钮,回掉只执行确定的事件 + */ +// if (isSingle) { +//// columnLineView.setVisibility(View.GONE); +// negtiveBn.setVisibility(View.GONE); +// } else { +// negtiveBn.setVisibility(View.VISIBLE); +//// columnLineView.setVisibility(View.VISIBLE); +// } + } + + @Override + public void show() { + super.show(); + refreshView(); + } + + /** + * 初始化界面控件 + */ + private void initView() { + negtiveBn = findViewById(R.id.negtive); + positiveBn = findViewById(R.id.positive); + titleTv = findViewById(R.id.title); + messageTv = findViewById(R.id.message); + imageIv = findViewById(R.id.image); +// columnLineView = findViewById(R.id.column_line); + showKeyboard(); + } + + public void showKeyboard() { + if (messageTv != null) { + //设置可获得焦点 + messageTv.setFocusable(true); + messageTv.setFocusableInTouchMode(true); + //请求获得焦点 + messageTv.requestFocus(); + //调用系统输入法 + InputMethodManager inputManager = (InputMethodManager) messageTv + .getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.showSoftInput(messageTv, 0); + } + } + + /** + * 设置确定取消按钮的回调 + */ + private OnClickBottomListener onClickBottomListener; + + public void setOnClickBottomListener(OnClickBottomListener onClickBottomListener) { + this.onClickBottomListener = onClickBottomListener; + } + + public interface OnClickBottomListener { + /** + * 点击确定按钮事件 + */ + void onPositiveClick(); + + /** + * 点击取消按钮事件 + */ + void onNegtiveClick(); + } + + public String getMessage() { + return message; + } + + public PasswordDialog setMessage(String message) { + this.message = message; + return this; + } + + public String getTitle() { + return title; + } + + public PasswordDialog setTitle(String title) { + this.title = title; + return this; + } + + public String getPositive() { + return positive; + } + + public PasswordDialog setPositive(String positive) { + this.positive = positive; + return this; + } + + public String getNegtive() { + return negtive; + } + + public PasswordDialog setNegtive(String negtive) { + this.negtive = negtive; + return this; + } + +// public SingleDialog setNegtiveText(String negtive) { +// negtiveBn.setText(negtive); +// return this; +// } + + public int getImageResId() { + return imageResId; + } + + public boolean isSingle() { + return isSingle; + } + + public PasswordDialog setSingle(boolean single) { + isSingle = single; + return this; + } + + public PasswordDialog setImageResId(int imageResId) { + this.imageResId = imageResId; + return this; + } + + public String getPassword() { + String passwd = messageTv.getText().toString(); + return passwd; + } + + @Override + public void dismiss() { + super.dismiss(); + } +} diff --git a/app/src/main/java/com/uiui/aios/fragment/AppListFragment.java b/app/src/main/java/com/uiui/aios/fragment/AppListFragment.java index 1caa0ec..d3c9dc8 100644 --- a/app/src/main/java/com/uiui/aios/fragment/AppListFragment.java +++ b/app/src/main/java/com/uiui/aios/fragment/AppListFragment.java @@ -10,9 +10,11 @@ import androidx.constraintlayout.widget.ConstraintLayout; import androidx.fragment.app.Fragment; import android.util.Log; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManager; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -21,12 +23,16 @@ import com.google.gson.JsonObject; import com.uiui.aios.R; import com.uiui.aios.bean.BaseResponse; import com.uiui.aios.bean.DesktopIcon; +import com.uiui.aios.dialog.PasswordDialog; import com.uiui.aios.network.NetInterfaceManager; import com.uiui.aios.service.NotificationService; import com.uiui.aios.utils.ApkUtils; import com.uiui.aios.utils.BitmapUtils; import com.uiui.aios.utils.IconUtils; import com.uiui.aios.utils.AppUsedTimeUtils; +import com.uiui.aios.utils.LauncherUtils; +import com.uiui.aios.utils.ToastUtil; +import com.uiui.aios.utils.Utils; import com.uiui.aios.view.MyGridLayout; import java.util.ArrayList; @@ -50,6 +56,7 @@ public class AppListFragment extends Fragment { private String mParam1; private String mParam2; + private Context mContext; private ArrayList mDesktopIcons; private MyGridLayout gridLayout; private String TAG = AppListFragment.class.getSimpleName(); @@ -94,6 +101,7 @@ public class AppListFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment rootView = inflater.inflate(R.layout.fragment_applist, container, false); + mContext = rootView.getContext(); initView(); return rootView; } @@ -121,7 +129,7 @@ public class AppListFragment extends Fragment { ConstraintLayout constraintLayout = view.findViewById(R.id.btn_booktag); DesktopIcon desktopIcon = mDesktopIcons.get(index); if (desktopIcon != null) { - String pkg =desktopIcon.getPackageName(); + String pkg = desktopIcon.getPackageName(); Log.e(TAG, "getView: " + pkg); int i = IconUtils.appClassNameList.indexOf(pkg); if (i != -1) { @@ -167,15 +175,46 @@ public class AppListFragment extends Fragment { public void onItemClick(View v, int index) { DesktopIcon desktopIcon = mDesktopIcons.get(index); if (desktopIcon != null) { - ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName()); - AppUsedTimeUtils.getInstance().setAppPackageName(desktopIcon.getPackageName()); - AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis()); - SendRunningApp(getActivity()); + switch (desktopIcon.getPackageName()) { + case "aios.exit": + showPassword(); + break; + default: + ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName()); + AppUsedTimeUtils.getInstance().setAppPackageName(desktopIcon.getPackageName()); + AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis()); + SendRunningApp(getActivity()); + } } } }); } + private void showPassword() { + PasswordDialog passwordDialog = new PasswordDialog(mContext); + passwordDialog.setTitle("退出关怀系统"); + passwordDialog.setOnClickBottomListener(new PasswordDialog.OnClickBottomListener() { + @Override + public void onPositiveClick() { + if ("666666".equals(passwordDialog.getPassword())) { + LauncherUtils.openLauncher3(mContext); + passwordDialog.dismiss(); + } else { + ToastUtil.show("密码错误"); + } + } + + @Override + public void onNegtiveClick() { + passwordDialog.dismiss(); + } + }); + passwordDialog.show(); + passwordDialog.getWindow().setGravity(Gravity.CENTER); + passwordDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + passwordDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + } + private void SendRunningApp(Context context) { String packageName = AppUsedTimeUtils.getInstance().getAppPackageName(); long time = AppUsedTimeUtils.getInstance().getStartTime(); diff --git a/app/src/main/java/com/uiui/aios/utils/ApkUtils.java b/app/src/main/java/com/uiui/aios/utils/ApkUtils.java index fd5c512..d81dd33 100644 --- a/app/src/main/java/com/uiui/aios/utils/ApkUtils.java +++ b/app/src/main/java/com/uiui/aios/utils/ApkUtils.java @@ -18,6 +18,7 @@ import android.util.Log; import androidx.annotation.RequiresApi; import com.uiui.aios.BuildConfig; +import com.uiui.aios.R; import com.uiui.aios.bean.DesktopIcon; import com.uiui.aios.receiver.InstallResultReceiver; @@ -32,7 +33,6 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; -import java.util.function.Predicate; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; @@ -212,6 +212,11 @@ public class ApkUtils { for (ApplicationInfo applicationInfo : infoHashMap.values()) { desktopIcons.add(DesktopIcon.creatDesktopIcon(context, applicationInfo)); } + DesktopIcon exitIcon = new DesktopIcon(); + exitIcon.setIcon(context.getDrawable(R.drawable.exit_icon)); + exitIcon.setLable("切换系统"); + exitIcon.setPackageName("aios.exit"); + desktopIcons.add(exitIcon); return desktopIcons; } diff --git a/app/src/main/java/com/uiui/aios/utils/LauncherUtils.java b/app/src/main/java/com/uiui/aios/utils/LauncherUtils.java new file mode 100644 index 0000000..83bfff8 --- /dev/null +++ b/app/src/main/java/com/uiui/aios/utils/LauncherUtils.java @@ -0,0 +1,140 @@ +package com.uiui.aios.utils; + +import android.app.role.RoleManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Build; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.text.TextUtils; +import android.util.Log; + +import java.util.List; +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +public class LauncherUtils { + private static final String TAG = LauncherUtils.class.getSimpleName(); + + public static void openLauncher3(Context context) { + setDefaultDesktop(context, Launcher3, Launcher3Class); +// ApkUtils.openPackage(mContext, Launcher3); + gotoLauncher(context); + } + + public static void gotoLauncher(Context context) { + Intent i = new Intent(Intent.ACTION_MAIN); + i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //android123提示如果是服务里调用,必须加入new task标识 + i.addCategory(Intent.CATEGORY_HOME); + context.startActivity(i); + } + + private static String Launcher3 = "com.android.launcher3"; + private static String Launcher3Class = "com.android.launcher3.Launcher"; + + public static void setDefaultDesktop(Context context, String pkg, String className) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + setRoleHolderAsUser(context, pkg); + Log.e(TAG, "setDefaultDesktop: setRoleHolderAsUser"); + } else { + //爱华设置,暂时屏蔽 +// setDefaultLauncher(mContext, pkg, className); + Log.e(TAG, "setDefaultDesktop: setDefaultLauncher"); + } +// String oldDesktop = (String) SPUtils.get(mContext, "default_launcher", ""); +// if (Objects.equals(oldDesktop, pkg)) { +// Log.e(TAG, "setDefaultDesktop: " + "数据一致"); +// return; +// } + Intent intent = new Intent("setDefaultLauncher"); + intent.putExtra("package", pkg); + intent.putExtra("className", className); +// if (JGYUtils.getInstance().checkAppPlatform() == MTKPlatform) { + Log.e(TAG, "setDefaultDesktop: MTK"); + //爱华定制 + intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.AoleReceiver")); + // TODO: 2022/7/6 有问题 + setDefaultLauncher(context, "com.android.transfer", "com.android.transfer.MainActivity"); + SystemProperties.set("persist.sys.launcher.pkgname", pkg); + SystemProperties.set("persist.sys.launcher.classname", className); +// } + intent.setPackage("com.android.settings"); + context.sendBroadcast(intent); +// ApkUtils.openPackage(mContext, pkg); + Log.e(TAG, "setDefaultDesktop: " + pkg + ":" + className); + Log.e(TAG, "setDefaultDesktop: " + "persist.sys.launcher.pkgname = " + SystemProperties.get("persist.sys.launcher.pkgname")); + Log.e(TAG, "setDefaultDesktop: " + "persist.sys.launcher.classname = " + SystemProperties.get("persist.sys.launcher.classname")); + } + + public static void setDefaultLauncher(Context context, String defPackageName, String defClassName) { + try { + if (!TextUtils.isEmpty(defPackageName) && !TextUtils.isEmpty(defClassName)) { + IntentFilter filter = new IntentFilter(); + filter.addAction("android.intent.action.MAIN"); + filter.addCategory("android.intent.category.HOME"); + filter.addCategory("android.intent.category.DEFAULT"); + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_HOME); + // 返回给定条件的所有ResolveInfo对象(本质上是Activity) + List list = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + int bestMatch = 0; + final int size = list.size(); + ComponentName[] set = new ComponentName[size]; + for (int i = 0; i < size; i++) { + ResolveInfo ri = list.get(i); + set[i] = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name); + if (ri.match > bestMatch) { + bestMatch = ri.match; + } + } + ComponentName preActivity = new ComponentName(defPackageName, defClassName); + context.getPackageManager().addPreferredActivity(filter, bestMatch, set, preActivity); + } + } catch (java.lang.SecurityException e) { + e.printStackTrace(); + Log.e(TAG, "setDefaultLauncher: " + e.getMessage()); + } + } + + + public static void setRoleHolderAsUser(Context context, String packageName) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + String roleName = "android.app.role.HOME"; + boolean add = true; + int flags = 0; + UserHandle user = android.os.Process.myUserHandle(); + Log.i("settingssssssstemf", (add ? "Adding" : "Removing") + " package as role holder, role: " + + roleName + ", package: " + packageName); +// if (JGYUtils.getInstance().checkAppPlatform() != JGYUtils.MTKPlatform) { + RoleManager roleManager = context.getSystemService(RoleManager.class); + Executor executor = context.getMainExecutor(); + Consumer callback = successful -> { + if (successful) { + Log.d("settingssssssstemf", "Package " + (add ? "added" : "removed") + + " as role holder, role: " + roleName + ", package: " + packageName); + } else { + Log.d("settingssssssstemf", "Failed to " + (add ? "add" : "remove") + + " package as role holder, role: " + roleName + ", package: " + + packageName); + } + }; + roleManager.addRoleHolderAsUser(roleName, packageName, flags, user, executor, callback); + Log.i("settingssssssstemf", "addRoleHolderAsUser done"); +// } + } + } + + public static boolean isDefaultHome(Context context) { + Intent intent = new Intent(Intent.ACTION_MAIN);//Intent.ACTION_VIEW + intent.addCategory("android.intent.category.HOME"); + intent.addCategory("android.intent.category.DEFAULT"); + PackageManager pm = context.getPackageManager(); + ResolveInfo info = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); + boolean isDefault = context.getPackageName().equals(info.activityInfo.packageName); + return isDefault; + } +} diff --git a/app/src/main/java/com/uiui/aios/utils/Utils.java b/app/src/main/java/com/uiui/aios/utils/Utils.java index a846748..23095b0 100644 --- a/app/src/main/java/com/uiui/aios/utils/Utils.java +++ b/app/src/main/java/com/uiui/aios/utils/Utils.java @@ -1,13 +1,20 @@ package com.uiui.aios.utils; import android.annotation.SuppressLint; +import android.app.role.RoleManager; +import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.os.BatteryManager; import android.os.Build; import android.os.Environment; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.text.TextUtils; import android.util.Log; import androidx.core.content.ContextCompat; @@ -16,8 +23,13 @@ import com.uiui.aios.BuildConfig; import java.io.File; import java.lang.reflect.Method; +import java.util.List; +import java.util.concurrent.Executor; +import java.util.function.Consumer; public class Utils { + private static final String TAG = Utils.class.getSimpleName(); + /** * 获取设备序列号 * @@ -83,4 +95,5 @@ public class Utils { return url.substring(position + 1); } + } diff --git a/app/src/main/res/drawable-hdpi/exit_icon.png b/app/src/main/res/drawable-hdpi/exit_icon.png new file mode 100644 index 0000000..5a609fc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/exit_icon.png differ diff --git a/app/src/main/res/drawable/bg_dialog.xml b/app/src/main/res/drawable/bg_dialog.xml index 3bfd5cd..4937102 100644 --- a/app/src/main/res/drawable/bg_dialog.xml +++ b/app/src/main/res/drawable/bg_dialog.xml @@ -5,5 +5,5 @@ android:width="0.8dp" android:color="#ffffff" /> - + diff --git a/app/src/main/res/drawable/et_bg.xml b/app/src/main/res/drawable/et_bg.xml new file mode 100644 index 0000000..5514a47 --- /dev/null +++ b/app/src/main/res/drawable/et_bg.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/joined_background.xml b/app/src/main/res/drawable/joined_background.xml index b025032..184e579 100644 --- a/app/src/main/res/drawable/joined_background.xml +++ b/app/src/main/res/drawable/joined_background.xml @@ -3,7 +3,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file