优化:细化权限请求判断

This commit is contained in:
pppscn 2022-01-28 23:14:07 +08:00
parent 5cf31b5b28
commit 146e5b725d
10 changed files with 480 additions and 12 deletions

View File

@ -27,9 +27,9 @@ android {
versionCode versionProps['versionCode'].toInteger()
versionName versionProps['versionName']
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
//ndk {
// abiFilters 'armeabi-v7a', 'x86_64'
//}
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'//, 'x86_64'
}
}
lintOptions {
checkReleaseBuilds false
@ -67,11 +67,11 @@ android {
abi {
enable true
reset()
include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
include 'armeabi-v7a', 'arm64-v8a', 'x86'//, 'x86_64'
universalApk true
}
}
def abiCodes = ['armeabi-v7a': 1, 'arm64-v8a': 2, 'x86': 3, 'x86_64': 4, 'universal': 5]
def abiCodes = ['universal': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'x86': 4, 'x86_64': 5]
android.applicationVariants.all { variant ->
// Assigns a different version code for each output APK.
variant.outputs.each {
@ -79,7 +79,7 @@ android {
def date = new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+08"))
def abiName = output.getFilter(com.android.build.OutputFile.ABI)
if (abiName == null) abiName = "universal"
output.versionCodeOverride = abiCodes.get(abiName, 0) * 10000 + variant.versionCode
output.versionCodeOverride = abiCodes.get(abiName, 0) * 100000 + variant.versionCode
output.outputFileName = "SmsForwarder_${variant.name}_${versionName}_${output.versionCodeOverride}_${date}_${abiName}.apk"
}
}

View File

@ -40,6 +40,9 @@
<uses-permission
android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<application
android:name=".MyApplication"
@ -51,12 +54,15 @@
android:largeHeap="true"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:ignore="UnusedAttribute">
<meta-data
android:name="ScopedStorage"
android:value="true" />
<activity
android:name=".MainActivity"
android:exported="true"

View File

@ -10,12 +10,18 @@ import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.idormy.sms.forwarder.receiver.RebootBroadcastReceiver;
import com.idormy.sms.forwarder.utils.CacheUtil;
import com.idormy.sms.forwarder.utils.CommonUtil;
import com.idormy.sms.forwarder.utils.SettingUtil;
import com.xuexiang.xupdate.easy.EasyUpdate;
import com.xuexiang.xupdate.proxy.impl.DefaultUpdateChecker;
import java.util.List;
public class AboutActivity extends AppCompatActivity {
@ -30,6 +36,36 @@ public class AboutActivity extends AppCompatActivity {
setContentView(R.layout.activity_about);
Log.d(TAG, "onCreate: " + RebootBroadcastReceiver.class.getName());
XXPermissions.with(this)
// 申请安装包权限
.permission(Permission.REQUEST_INSTALL_PACKAGES)
// 申请通知栏权限
.permission(Permission.NOTIFICATION_SERVICE)
.request(new OnPermissionCallback() {
@Override
public void onGranted(List<String> permissions, boolean all) {
if (all) {
Toast.makeText(getBaseContext(), R.string.toast_granted_all, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), R.string.toast_granted_part, Toast.LENGTH_SHORT).show();
}
SettingUtil.switchEnableSms(true);
}
@Override
public void onDenied(List<String> permissions, boolean never) {
if (never) {
Toast.makeText(getBaseContext(), R.string.toast_denied_never, Toast.LENGTH_SHORT).show();
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(AboutActivity.this, permissions);
} else {
Toast.makeText(getBaseContext(), R.string.toast_denied, Toast.LENGTH_SHORT).show();
}
SettingUtil.switchEnableSms(false);
}
});
final TextView version_now = findViewById(R.id.version_now);
Button check_version_now = findViewById(R.id.check_version_now);
try {

View File

@ -27,6 +27,9 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.idormy.sms.forwarder.adapter.LogAdapter;
import com.idormy.sms.forwarder.model.vo.LogVo;
import com.idormy.sms.forwarder.sender.HttpServer;
@ -140,6 +143,53 @@ public class MainActivity extends AppCompatActivity implements RefreshListView.I
//检查权限是否获取
PackageManager pm = getPackageManager();
CommonUtil.CheckPermission(pm, this);
XXPermissions.with(this)
// 接收短信
.permission(Permission.RECEIVE_SMS)
// 发送短信
.permission(Permission.SEND_SMS)
// 读取短信
.permission(Permission.READ_SMS)
// 读取电话状态
.permission(Permission.READ_PHONE_STATE)
// 读取手机号码
.permission(Permission.READ_PHONE_NUMBERS)
// 读取通话记录
.permission(Permission.READ_CALL_LOG)
// 读取联系人
.permission(Permission.READ_CONTACTS)
// 储存权限
.permission(Permission.Group.STORAGE)
// 申请安装包权限
//.permission(Permission.REQUEST_INSTALL_PACKAGES)
// 申请通知栏权限
.permission(Permission.NOTIFICATION_SERVICE)
// 申请系统设置权限
//.permission(Permission.WRITE_SETTINGS)
.request(new OnPermissionCallback() {
@Override
public void onGranted(List<String> permissions, boolean all) {
if (all) {
Toast.makeText(getBaseContext(), R.string.toast_granted_all, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), R.string.toast_granted_part, Toast.LENGTH_SHORT).show();
}
SettingUtil.switchEnableSms(true);
}
@Override
public void onDenied(List<String> permissions, boolean never) {
if (never) {
Toast.makeText(getBaseContext(), R.string.toast_denied_never, Toast.LENGTH_SHORT).show();
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(MainActivity.this, permissions);
} else {
Toast.makeText(getBaseContext(), R.string.toast_denied, Toast.LENGTH_SHORT).show();
}
SettingUtil.switchEnableSms(false);
}
});
//计算浮动按钮位置
FloatingActionButton btnFloat = findViewById(R.id.btnCleanLog);

View File

@ -10,11 +10,15 @@ import android.content.SharedPreferences;
import android.os.Build;
import android.util.Log;
import com.hjq.permissions.XXPermissions;
import com.hjq.toast.ToastUtils;
import com.hjq.toast.style.WhiteToastStyle;
import com.idormy.sms.forwarder.receiver.SimStateReceiver;
import com.idormy.sms.forwarder.sender.SendHistory;
import com.idormy.sms.forwarder.service.BatteryService;
import com.idormy.sms.forwarder.service.FrontService;
import com.idormy.sms.forwarder.utils.Define;
import com.idormy.sms.forwarder.utils.PermissionInterceptor;
import com.idormy.sms.forwarder.utils.PhoneUtils;
import com.idormy.sms.forwarder.utils.SettingUtil;
import com.idormy.sms.forwarder.utils.SharedPreferencesHelper;
@ -51,6 +55,11 @@ public class MyApplication extends Application {
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(getApplicationContext());
// 初始化吐司工具类
ToastUtils.init(this, new WhiteToastStyle());
// 设置权限申请拦截器全局设置
XXPermissions.setInterceptor(new PermissionInterceptor());
//友盟统计
sharedPreferencesHelper = new SharedPreferencesHelper(this, "umeng");
//设置LOG开关默认为false

View File

@ -28,6 +28,9 @@ import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.idormy.sms.forwarder.receiver.RebootBroadcastReceiver;
import com.idormy.sms.forwarder.sender.HttpServer;
import com.idormy.sms.forwarder.sender.SenderUtil;
@ -133,9 +136,45 @@ public class SettingActivity extends AppCompatActivity {
switch_enable_sms.setChecked(SettingUtil.getSwitchEnableSms());
switch_enable_sms.setOnCheckedChangeListener((buttonView, isChecked) -> {
//TODO:校验使用短信转发必备的权限
SettingUtil.switchEnableSms(isChecked);
Log.d(TAG, "switchEnableSms:" + isChecked);
if (isChecked) {
//检查权限是否获取
PackageManager pm = getPackageManager();
CommonUtil.CheckPermission(pm, this);
XXPermissions.with(this)
// 接收短信
.permission(Permission.RECEIVE_SMS)
// 发送短信
.permission(Permission.SEND_SMS)
// 读取短信
.permission(Permission.READ_SMS)
.request(new OnPermissionCallback() {
@Override
public void onGranted(List<String> permissions, boolean all) {
if (all) {
Toast.makeText(getBaseContext(), R.string.toast_granted_all, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), R.string.toast_granted_part, Toast.LENGTH_SHORT).show();
}
SettingUtil.switchEnableSms(true);
}
@Override
public void onDenied(List<String> permissions, boolean never) {
if (never) {
Toast.makeText(getBaseContext(), R.string.toast_denied_never, Toast.LENGTH_SHORT).show();
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(SettingActivity.this, permissions);
} else {
Toast.makeText(getBaseContext(), R.string.toast_denied, Toast.LENGTH_SHORT).show();
}
SettingUtil.switchEnableSms(false);
}
});
} else {
SettingUtil.switchEnableSms(false);
}
});
}
@ -154,9 +193,47 @@ public class SettingActivity extends AppCompatActivity {
return;
}
//TODO:校验使用来电转发必备的权限
SettingUtil.switchEnablePhone(isChecked);
Log.d(TAG, "switchEnablePhone:" + isChecked);
if (isChecked) {
//检查权限是否获取
PackageManager pm = getPackageManager();
CommonUtil.CheckPermission(pm, this);
XXPermissions.with(this)
// 读取电话状态
.permission(Permission.READ_PHONE_STATE)
// 读取手机号码
.permission(Permission.READ_PHONE_NUMBERS)
// 读取通话记录
.permission(Permission.READ_CALL_LOG)
// 读取联系人
.permission(Permission.READ_CONTACTS)
.request(new OnPermissionCallback() {
@Override
public void onGranted(List<String> permissions, boolean all) {
if (all) {
Toast.makeText(getBaseContext(), R.string.toast_granted_all, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), R.string.toast_granted_part, Toast.LENGTH_SHORT).show();
}
SettingUtil.switchEnableSms(true);
}
@Override
public void onDenied(List<String> permissions, boolean never) {
if (never) {
Toast.makeText(getBaseContext(), R.string.toast_denied_never, Toast.LENGTH_SHORT).show();
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(SettingActivity.this, permissions);
} else {
Toast.makeText(getBaseContext(), R.string.toast_denied, Toast.LENGTH_SHORT).show();
}
SettingUtil.switchEnableSms(false);
}
});
} else {
SettingUtil.switchEnablePhone(false);
}
});
check_box_call_type_1.setOnCheckedChangeListener((buttonView, isChecked) -> {

View File

@ -98,7 +98,7 @@ public class PhoneStateReceiver extends BroadcastReceiver {
String viaNumber = callInfo.getViaNumber(); //来源号码
//卡槽判断获取卡槽失败时默认为卡槽1
String simInfo = "";
String simInfo;
int simId = 1;
Log.d(TAG, "getSubscriptionId = " + callInfo.getSubscriptionId()); //TODO:这里的SubscriptionId跟短信的不一样
if (callInfo.getSubscriptionId() != -1) {

View File

@ -0,0 +1,282 @@
package com.idormy.sms.forwarder.utils;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import androidx.appcompat.app.AlertDialog;
import com.hjq.permissions.IPermissionInterceptor;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.hjq.toast.ToastUtils;
import com.idormy.sms.forwarder.R;
import java.util.ArrayList;
import java.util.List;
/**
* author : Android 轮子哥
* github : https://github.com/getActivity/XXPermissions
* time : 2021/01/04
* desc : 权限申请拦截器
*/
@SuppressWarnings({"deprecation", "CommentedOutCode"})
public final class PermissionInterceptor implements IPermissionInterceptor {
// @Override
// public void requestPermissions(Activity activity, OnPermissionCallback callback, List<String> allPermissions) {
// // 这里的 Dialog 只是示例没有用 DialogFragment 来处理 Dialog 生命周期
// new AlertDialog.Builder(activity)
// .setTitle(R.string.common_permission_hint)
// .setMessage(R.string.common_permission_message)
// .setPositiveButton(R.string.common_permission_granted, new DialogInterface.OnClickListener() {
//
// @Override
// public void onClick(DialogInterface dialog, int which) {
// dialog.dismiss();
// PermissionFragment.beginRequest(activity, new ArrayList<>(allPermissions), PermissionInterceptor.this, callback);
// }
// })
// .setNegativeButton(R.string.common_permission_denied, new DialogInterface.OnClickListener() {
//
// @Override
// public void onClick(DialogInterface dialog, int which) {
// dialog.dismiss();
// }
// })
// .show();
// }
@Override
public void grantedPermissions(Activity activity, List<String> allPermissions, List<String> grantedPermissions,
boolean all, OnPermissionCallback callback) {
if (callback != null) {
callback.onGranted(grantedPermissions, all);
}
}
@SuppressWarnings("ConstantConditions")
@Override
public void deniedPermissions(Activity activity, List<String> allPermissions, List<String> deniedPermissions,
boolean never, OnPermissionCallback callback) {
if (callback != null) {
callback.onDenied(deniedPermissions, never);
}
if (never) {
showPermissionDialog(activity, deniedPermissions);
return;
}
if (deniedPermissions.size() == 1 && Permission.ACCESS_BACKGROUND_LOCATION.equals(deniedPermissions.get(0))) {
ToastUtils.show(R.string.common_permission_fail_4);
return;
}
ToastUtils.show(R.string.common_permission_fail_1);
if (callback == null) {
return;
}
callback.onDenied(deniedPermissions, never);
}
/**
* 显示授权对话框
*/
protected void showPermissionDialog(Activity activity, List<String> permissions) {
// 这里的 Dialog 只是示例没有用 DialogFragment 来处理 Dialog 生命周期
new AlertDialog.Builder(activity)
.setTitle(R.string.common_permission_alert)
.setCancelable(false)
.setMessage(getPermissionHint(activity, permissions))
.setPositiveButton(R.string.common_permission_goto, (dialog, which) -> {
dialog.dismiss();
XXPermissions.startPermissionActivity(activity, permissions);
})
.show();
}
/**
* 根据权限获取提示
*/
protected String getPermissionHint(Context context, List<String> permissions) {
if (permissions == null || permissions.isEmpty()) {
return context.getString(R.string.common_permission_fail_2);
}
List<String> hints = new ArrayList<>();
for (String permission : permissions) {
switch (permission) {
case Permission.READ_EXTERNAL_STORAGE:
case Permission.WRITE_EXTERNAL_STORAGE:
case Permission.MANAGE_EXTERNAL_STORAGE: {
String hint = context.getString(R.string.common_permission_storage);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.CAMERA: {
String hint = context.getString(R.string.common_permission_camera);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.RECORD_AUDIO: {
String hint = context.getString(R.string.common_permission_microphone);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.ACCESS_FINE_LOCATION:
case Permission.ACCESS_COARSE_LOCATION:
case Permission.ACCESS_BACKGROUND_LOCATION: {
String hint;
if (!permissions.contains(Permission.ACCESS_FINE_LOCATION) &&
!permissions.contains(Permission.ACCESS_COARSE_LOCATION)) {
hint = context.getString(R.string.common_permission_location_background);
} else {
hint = context.getString(R.string.common_permission_location);
}
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.BLUETOOTH_SCAN:
case Permission.BLUETOOTH_CONNECT:
case Permission.BLUETOOTH_ADVERTISE: {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
String hint = context.getString(R.string.common_permission_bluetooth);
if (!hints.contains(hint)) {
hints.add(hint);
}
}
break;
}
case Permission.READ_PHONE_STATE:
case Permission.CALL_PHONE:
case Permission.ADD_VOICEMAIL:
case Permission.USE_SIP:
case Permission.READ_PHONE_NUMBERS:
case Permission.ANSWER_PHONE_CALLS: {
String hint = context.getString(R.string.common_permission_phone);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.GET_ACCOUNTS:
case Permission.READ_CONTACTS:
case Permission.WRITE_CONTACTS: {
String hint = context.getString(R.string.common_permission_contacts);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.READ_CALENDAR:
case Permission.WRITE_CALENDAR: {
String hint = context.getString(R.string.common_permission_calendar);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.READ_CALL_LOG:
case Permission.WRITE_CALL_LOG:
case Permission.PROCESS_OUTGOING_CALLS: {
String hint = context.getString(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ?
R.string.common_permission_call_log : R.string.common_permission_phone);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.BODY_SENSORS: {
String hint = context.getString(R.string.common_permission_sensors);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.ACTIVITY_RECOGNITION: {
String hint = context.getString(R.string.common_permission_activity_recognition);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.SEND_SMS:
case Permission.RECEIVE_SMS:
case Permission.READ_SMS:
case Permission.RECEIVE_WAP_PUSH:
case Permission.RECEIVE_MMS: {
String hint = context.getString(R.string.common_permission_sms);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.REQUEST_INSTALL_PACKAGES: {
String hint = context.getString(R.string.common_permission_install);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.SYSTEM_ALERT_WINDOW: {
String hint = context.getString(R.string.common_permission_window);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.WRITE_SETTINGS: {
String hint = context.getString(R.string.common_permission_setting);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.NOTIFICATION_SERVICE: {
String hint = context.getString(R.string.common_permission_notification);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
case Permission.PACKAGE_USAGE_STATS: {
String hint = context.getString(R.string.common_permission_task);
if (!hints.contains(hint)) {
hints.add(hint);
}
break;
}
default:
break;
}
}
if (!hints.isEmpty()) {
StringBuilder builder = new StringBuilder();
for (String text : hints) {
if (builder.length() == 0) {
builder.append(text);
} else {
builder.append("")
.append(text);
}
}
builder.append(" ");
return context.getString(R.string.common_permission_fail_3, builder.toString());
}
return context.getString(R.string.common_permission_fail_2);
}
}

View File

@ -424,4 +424,8 @@
<string name="common_permission_setting">系统设置权限</string>
<string name="common_permission_notification">通知栏权限</string>
<string name="common_permission_task">查看使用情况权限</string>
<string name="toast_granted_all">获取所有必需的权限成功!</string>
<string name="toast_granted_part">获取部分权限成功但部分权限未正常授予APP部分功能可能受限</string>
<string name="toast_denied_never">被永久拒绝授权,请前往系统设置手动授予权限!</string>
<string name="toast_denied">获取必需的权限失败APP功能可能受限</string>
</resources>

View File

@ -423,4 +423,8 @@
<string name="common_permission_setting">系统设置权限</string>
<string name="common_permission_notification">通知栏权限</string>
<string name="common_permission_task">查看使用情况权限</string>
<string name="toast_granted_all">获取所有必需的权限成功!</string>
<string name="toast_granted_part">获取部分权限成功但部分权限未正常授予APP部分功能可能受限</string>
<string name="toast_denied_never">被永久拒绝授权,请前往系统设置手动授予权限!</string>
<string name="toast_denied">获取必需的权限失败APP功能可能受限</string>
</resources>