第一次提交

This commit is contained in:
被淹死的鱼
2026-03-11 18:26:29 +08:00
commit cd3b53759e
8532 changed files with 522078 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
package com.fengliyan.base;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.caivideo.base.test", appContext.getPackageName());
}
}

View File

@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fengliyan.base" />

View File

@@ -0,0 +1,5 @@
package com.fengliyan.base.base;
public interface AnyCallback<T> {
void callback(T t);
}

View File

@@ -0,0 +1,26 @@
package com.fengliyan.base.base;
import android.content.Context;
/**
* MUNA框架的初始化类所有初始化工作在此进行应在使用其它组件前进行初始化
* Created by siva on 16/1/14.
*/
public class BaseFramework {
private static boolean sInited = false;
public synchronized static void init(Context applicationContext) {
if (null == applicationContext) {
throw new IllegalArgumentException("applicationContext cannot be null");
}
if (sInited) {
return;
}
ContextHolder.init(applicationContext.getApplicationContext()); //初始化上下文保持类
sInited = true;
}
}

View File

@@ -0,0 +1,41 @@
package com.fengliyan.base.base;
import android.content.Context;
/**
* 可以通过该类获取应用上下文,需要在使用其它组件之前对其进行初始化
* Created by siva on 16/1/13.
*/
public final class ContextHolder {
private static boolean sInited = false;
private static Context sApplicationContext;
/**
* 使用其它组件之前对其进行初始化由MunaFramework调用无需直接使用
*
* @param applicationContext 指定ApplicationContext
*/
public synchronized static void init(Context applicationContext) {
if (null == applicationContext) {
throw new IllegalArgumentException("applicationContext cannot be null");
}
if (sInited) {
return;
}
sApplicationContext = applicationContext;
sInited = true;
}
/**
* 获取ApplicationContext对像
*
* @return
*/
public static Context getApplicationContext() {
return sApplicationContext;
}
}

View File

@@ -0,0 +1,112 @@
package com.fengliyan.base.base.bean;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;
/**
* Created by siva on 16/1/17.
*/
public abstract class BaseBean implements Serializable {
/**
* 序列号
*/
private static final long serialVersionUID = 2249325746833199332L;
/**
* 访问控制器,序列化的时候,不做处理
*/
private transient ThreadLocal<BaseBean> visitor = new ThreadLocal<BaseBean>() {
@Override
protected BaseBean initialValue() {
return null;
}
};
private String mSimpleName = getClass().getSimpleName();
/**
* 避免子类中相互引用引起输出toString时栈溢出
*
* @return String 返回字符串
*/
private String toString0() {
List<PropertyDescriptor> props = PropertyDescriptorHelper.getPropertyDescriptors(this);
Object[] params = new Object[0];
Object result;
boolean isFirst = true;
Method m;
boolean accessible;
StringBuilder strBuilder = new StringBuilder();
strBuilder.append(getClass().getName()).append('{');
for (PropertyDescriptor descriptor : props) {
if ("class".equals(descriptor.getName())) {
continue;
}
m = descriptor.getReadMethod();
if (m == null) {
continue;
}
accessible = m.isAccessible();
if (!accessible) {
m.setAccessible(true);
}
try {
result = m.invoke(this, params);
if (!isFirst) {
strBuilder.append(", ");
} else {
isFirst = false;
}
strBuilder.append(descriptor.getName()).append(": ");
// 对是否为String分别区分
if (result instanceof String) {
strBuilder.append('"');
strBuilder.append(result);
strBuilder.append('"');
} else {
strBuilder.append(result);
}
} catch (Exception e) {
}
if (!accessible) {
m.setAccessible(false);
}
}
strBuilder.append('}');
return strBuilder.toString();
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
if (visitor.get() == null) {
visitor.set(this);
try {
return toString0();
} finally {
visitor.set(null);
}
}
return mSimpleName + "@" + Integer.toHexString(hashCode());
}
}

View File

@@ -0,0 +1,61 @@
package com.fengliyan.base.base.bean;
import java.lang.reflect.Method;
/**
* Created by siva on 16/1/17.
*/
public final class PropertyDescriptor {
/**
* 属性名称
*/
private String name;
/**
* 显示名称
*/
private String displayName;
/**
* 读方法
*/
private Method readMethod;
/**
* 写方法
*/
private Method writeMethod;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public Method getReadMethod() {
return readMethod;
}
public void setReadMethod(Method readMethod) {
this.readMethod = readMethod;
}
public Method getWriteMethod() {
return writeMethod;
}
public void setWriteMethod(Method writeMethod) {
this.writeMethod = writeMethod;
}
}

View File

@@ -0,0 +1,69 @@
package com.fengliyan.base.base.bean;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by siva on 16/1/17.
*/
public final class PropertyDescriptorHelper {
public static List<PropertyDescriptor> getPropertyDescriptors(Class<?> type) {
List<PropertyDescriptor> lsDescriptor = new ArrayList<PropertyDescriptor>();
Method[] aryMethod = type.getMethods();
Map<String, Method> dicMethod = new HashMap<String, Method>();
for (Method method : aryMethod) {
if (method.getName().startsWith("set")
&& method.getParameterTypes() != null
&& method.getParameterTypes().length == 1) {
dicMethod.put(method.getName(), method);
}
}
for (Method method : aryMethod) {
if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) {
String name = Character.toLowerCase(method.getName().charAt(3))
+ method.getName().substring(4, method.getName().length());
PropertyDescriptor desc = new PropertyDescriptor();
desc.setDisplayName(name);
desc.setName(name);
desc.setReadMethod(method);
String setMethodName = "set" + name.substring(0, 1).toUpperCase()
+ name.substring(1, name.length());
if (dicMethod.containsKey(setMethodName)) {
desc.setWriteMethod(dicMethod.get(setMethodName));
}
lsDescriptor.add(desc);
} else if (method.getName().startsWith("is")
&& method.getParameterTypes().length == 0) {
String name = Character.toLowerCase(method.getName().charAt(2))
+ method.getName().substring(3, method.getName().length());
PropertyDescriptor desc = new PropertyDescriptor();
desc.setDisplayName(name);
desc.setName(name);
desc.setReadMethod(method);
String setMethodName = "set" + name.substring(0, 1).toUpperCase()
+ name.substring(1, name.length());
if (dicMethod.containsKey(setMethodName)) {
desc.setWriteMethod(dicMethod.get(setMethodName));
}
lsDescriptor.add(desc);
}
}
return lsDescriptor;
}
public static List<PropertyDescriptor> getPropertyDescriptors(Object bean) {
return getPropertyDescriptors(bean.getClass());
}
}

View File

@@ -0,0 +1,31 @@
package com.fengliyan.base.base.permission;
import android.content.Context;
import android.content.Intent;
/**
* 一个简化的权限回调,使用者只需要处理成功回调
* Created by yangjinbo on 2016-5-3.
*/
public abstract class AbsPermissionResultCallBack extends BasePermissionResultCallBack {
private static Context mContext = PermissionHelper.getApplicationContext();
protected String message;
@Override
public void onPermissionDenied(String... permissions) {
if (mContext == null) {
return;
}
Intent intent = new Intent(mContext, PermissionDeniedActivity.class);
intent.putExtra("permissions", permissions);
if (message != null) {
intent.putExtra(PermissionDeniedActivity.DENIED_MESSAGE_EXTRA, message);
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
}

View File

@@ -0,0 +1,31 @@
package com.fengliyan.base.base.permission;
import android.content.Context;
import android.content.SharedPreferences;
import com.fengliyan.base.base.ContextHolder;
/**
* Created by zhanghuaijie on 16/9/2.
*/
public abstract class BasePermissionResultCallBack implements PermissionResultCallBack {
public static final String NEVER_ASK_PERMISSIONS = "never_ask_permissions";
@Override
public void onRationalShow(PermissionRequest permissionRequest) {
permissionRequest.proceed();
}
@Override
public void onNeverAskAgain(String... strings) {
SharedPreferences neverAskPermissions = ContextHolder.getApplicationContext().getSharedPreferences(NEVER_ASK_PERMISSIONS, Context.MODE_PRIVATE);
if (neverAskPermissions != null) {
SharedPreferences.Editor editor = neverAskPermissions.edit();
for (String permission : strings) {
editor.putBoolean(PermissionHelper.getPermissionExplain(permission), true);
}
editor.apply();
}
}
}

View File

@@ -0,0 +1,124 @@
package com.fengliyan.base.base.permission;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.Window;
/**
* Created by yangjinbo on 2016-6-14.
*/
public class PermissionDeniedActivity extends Activity {
private static final String TAG = "PermDeniedActivity";
public static final String DENIED_MESSAGE_EXTRA = "denied_message_extra";
public static final int REQUEST_CODE_START_APP_SETTING = 3;
private PermissionDialog permissionDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, TAG + "onCreate");
if (savedInstanceState == null) {
handleOnPermissionDeniedIntent(getIntent());
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleOnPermissionDeniedIntent(intent);
}
private void handleOnPermissionDeniedIntent(Intent intent) {
String[] permissions;
permissions = intent.getStringArrayExtra("permissions");
permissionDialog = new PermissionDialog(this, permissions);
permissionDialog.show();
String msg = intent.getStringExtra(DENIED_MESSAGE_EXTRA);
if (msg == null) {
msg = "由于一些必要的权限被拒绝了,相应的功能无法使用!";
}
if (permissions == null || permissions.length < 1) {
this.finish();
return;
}
AlertDialog.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new AlertDialog.Builder(this, android.R.style.Theme_Material_Light_Dialog_Alert);
} else {
builder = new AlertDialog.Builder(this);
}
StringBuilder permissionNames = new StringBuilder();
for (String permission : permissions) {
permissionNames.append(PermissionHelper.getPermissionExplain(permission))
.append("");
}
permissionNames.deleteCharAt(permissionNames.length() - 1);
final SpannableStringBuilder message = new SpannableStringBuilder(msg + "请前往设置中打开");
int start = message.length();
message.append(permissionNames);
message.setSpan(new ForegroundColorSpan(Color.RED), start, message.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
message.append("权限后使用。");
builder.setMessage(message);
builder.setPositiveButton("立即设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
try {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivityForResult(intent, REQUEST_CODE_START_APP_SETTING);
} catch (Exception e) {
try {
intent.setAction(Settings.ACTION_APPLICATION_SETTINGS);
startActivityForResult(intent, REQUEST_CODE_START_APP_SETTING);
} catch (Exception e1) {
try {
intent.setAction(Settings.ACTION_SETTINGS);
startActivityForResult(intent, REQUEST_CODE_START_APP_SETTING);
} catch (Exception ignore) {
}
}
} finally {
finish();
}
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setCancelable(false);
AlertDialog dialog = builder.create();
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.show();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (permissionDialog != null && permissionDialog.isShowing()) {
permissionDialog.dismiss();
}
}
}

View File

@@ -0,0 +1,91 @@
package com.fengliyan.base.base.permission;
import android.Manifest;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Window;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.fengliyan.base.R;
import java.util.HashMap;
public class PermissionDialog extends Dialog {
private static final String TAG = "PermissionDialog";
private Context mContext;
private String[] permissions;
private TextView tv_permission;
public PermissionDialog(@NonNull Context context, String[] permission) {
super(context);
mContext = context;
this.permissions = permission;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_permission);
Window window = this.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setGravity(Gravity.TOP);
}
// setCanceledOnTouchOutside(false);
initView();
}
private void initView() {
tv_permission = findViewById(R.id.tv_permission);
HashMap<Integer, String> map = new HashMap<>();
for (String s : permissions) {
switch (s) {
case Manifest.permission.ACCESS_COARSE_LOCATION:
case Manifest.permission.ACCESS_FINE_LOCATION:
map.put(1, "定位权限用于完善资料、编辑资料、推荐同城等场景;");
break;
case Manifest.permission.CAMERA:
map.put(2, "相机权限用于拍照、录制、视频通话、认证等场景;");
break;
case Manifest.permission.WRITE_EXTERNAL_STORAGE:
case Manifest.permission.READ_EXTERNAL_STORAGE:
map.put(3, "读写手机存储权限用于访问相册及储存图片、文件等场景;");
break;
case Manifest.permission.RECORD_AUDIO:
map.put(4, "访问麦克风用于发送语音、语音通话等场景;");
break;
}
}
StringBuilder str = new StringBuilder();
for (int key : map.keySet()) {
String value = map.get(key);
System.out.println("key=" + key + ", vlaue=" + value);
str.append(value);
}
tv_permission.setText(str);
}
@Override
public void show() {
boolean isCheck = true;
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(mContext, permission) != PackageManager.PERMISSION_GRANTED) {
isCheck = false;
}
}
if (!isCheck) {
super.show();
}
}
}

View File

@@ -0,0 +1,227 @@
package com.fengliyan.base.base.permission;
import android.Manifest.permission;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Looper;
import android.provider.Settings;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.fengliyan.base.base.ContextHolder;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
public class PermissionHelper {
private static Context sApplicationContext = ContextHolder.getApplicationContext();
private static SparseArray<PermissionRequestImpl> sRequests = new SparseArray<>();
private static AtomicInteger sRequestCodeGen = new AtomicInteger(1);
private static int getRequestCode() {
return sRequestCodeGen.getAndIncrement();
}
public static Context getApplicationContext() {
return sApplicationContext;
}
private static class PermissionRequestImpl implements PermissionRequest {
private String[] mPermissions = null;
private String[] mNeedReqPermissions = null;
private PermissionResultCallBack mResultCallBack = null;
public PermissionRequestImpl(String[] permissions, String[] needReqPermissions,
PermissionResultCallBack resultCallBack) {
this.mPermissions = permissions;
this.mResultCallBack = resultCallBack;
this.mNeedReqPermissions = needReqPermissions;
}
@Override
public void proceed() {
int requestCode = getRequestCode() & 0x7fff;
sRequests.put(requestCode, this);
requestPermissions(mNeedReqPermissions, requestCode);
}
@Override
public void cancel() {
mResultCallBack.onPermissionDenied(mNeedReqPermissions);
}
}
/**
* 用于请求权限
*
* @param permissions 请求的权限列表
* @param callBack 结果回调
*/
public static void request(@NonNull String[] permissions, @NonNull PermissionResultCallBack callBack) {
if (sApplicationContext == null) {
throw new RuntimeException("Before call PermissionHelper.request(), you must call PermissionHelper.init() once to set a context!");
}
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new RuntimeException("request permission only can run in MainThread!");
}
if (permissions.length == 0) {
callBack.onPermissionGranted();
return;
}
if (VERSION.SDK_INT < VERSION_CODES.M) {
callBack.onPermissionGranted();
return;
}
String[] needReqPermissions = getPermissionListNeedReq(permissions);
if (needReqPermissions == null || needReqPermissions.length == 0) {
callBack.onPermissionGranted();
} else {
PermissionRequestImpl request = new PermissionRequestImpl(permissions, needReqPermissions, callBack);
callBack.onRationalShow(request);
}
}
/**
* 通过开启一个新的activity作为申请权限的媒介
*/
private static void requestPermissions(String[] permissions, int requestCode) {
Intent intent = new Intent(sApplicationContext, PermissionHelperActivity.class);
intent.putExtra("permissions", permissions);
intent.putExtra("requestCode", requestCode);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sApplicationContext.startActivity(intent);
}
/**
* 获取需要请求的权限
*
* @return 需要请求的权限数组
*/
private static String[] getPermissionListNeedReq(String permissions[]) {
ArrayList<String> needReqPermissions = new ArrayList<>();
for (String permissionName : permissions) {
// android.permission.WRITE_SETTINGS, android.permission.SYSTEM_ALERT_WINDOW 两个权限需要特殊处理
if (permission.WRITE_SETTINGS.equals(permissionName)) {
if (VERSION.SDK_INT >= VERSION_CODES.M) {
if (!Settings.System.canWrite(sApplicationContext)) {
needReqPermissions.add(permissionName);
}
}
continue;
}
if (permission.SYSTEM_ALERT_WINDOW.equals(permissionName)) {
if (VERSION.SDK_INT >= VERSION_CODES.M) {
if (!Settings.canDrawOverlays(sApplicationContext)) {
needReqPermissions.add(permissionName);
}
}
continue;
}
int checkRes = ContextCompat.checkSelfPermission(sApplicationContext, permissionName);
if (checkRes != PackageManager.PERMISSION_GRANTED) {
needReqPermissions.add(permissionName);
}
// if (!Utility.checkPermission(sApplicationContext, permissionName)) {
// needReqPermissions.add(permissionName);
// }
}
if (needReqPermissions.size() == 0) {
return null;
} else {
String[] ret = new String[needReqPermissions.size()];
return needReqPermissions.toArray(ret);
}
}
/**
* 申请权限结果返回
*/
static void onRequestPermissionResult(int requestCode, ArrayList<String> deniedPermissions, ArrayList<String> neverAskPermissions) {
PermissionRequestImpl request = sRequests.get(requestCode);
sRequests.remove(requestCode);
String[] stillNeedReqPermissions = getPermissionListNeedReq(request.mPermissions);
if (request == null) {
return;
}
if (neverAskPermissions.size() > 0) {
request.mResultCallBack.onNeverAskAgain(neverAskPermissions.toArray(new String[neverAskPermissions.size()]));
}
if (deniedPermissions.size() > 0) {
request.mResultCallBack.onPermissionDenied(deniedPermissions.toArray(new String[deniedPermissions.size()]));
} else if (stillNeedReqPermissions != null && stillNeedReqPermissions.length > 0) {
request.mResultCallBack.onPermissionDenied(stillNeedReqPermissions);
} else {
request.mResultCallBack.onPermissionGranted();
}
}
/**
* 根据权限获取相应的中文名称
*
* @param permissionName 权限
* @return 中文名称
*/
public static String getPermissionExplain(String permissionName) {
if (permissionName == null) {
return null;
} else if (permissionName.equals(permission.READ_CALENDAR)
|| permissionName.equals(permission.WRITE_CALENDAR)) {
return "日历";
} else if (permissionName.equals(permission.CAMERA)) {
return "相机";
} else if (permissionName.equals(permission.READ_CONTACTS)
|| permissionName.equals(permission.WRITE_CONTACTS)
|| permissionName.equals(permission.GET_ACCOUNTS)) {
return "通讯录";
} else if (permissionName.equals(permission.ACCESS_FINE_LOCATION)
|| permissionName.equals(permission.ACCESS_COARSE_LOCATION)) {
return "位置信息";
} else if (permissionName.equals(permission.RECORD_AUDIO)) {
return "麦克风";
} else if (permissionName.equals(permission.READ_PHONE_STATE)
|| permissionName.equals(permission.CALL_PHONE)
|| permissionName.equals(permission.READ_CALL_LOG)
|| permissionName.equals(permission.WRITE_CALL_LOG)
|| permissionName.equals(permission.ADD_VOICEMAIL)
|| permissionName.equals(permission.USE_SIP)
|| permissionName.equals(permission.PROCESS_OUTGOING_CALLS)) {
return "电话";
} else if (permissionName.equals(permission.BODY_SENSORS)) {
return "身体传感器";
} else if (permissionName.equals(permission.SEND_SMS)
|| permissionName.equals(permission.RECEIVE_SMS)
|| permissionName.equals(permission.READ_SMS)
|| permissionName.equals(permission.RECEIVE_WAP_PUSH)
|| permissionName.equals(permission.RECEIVE_MMS)) {
return "短信";
} else if (permissionName.equals(permission.READ_EXTERNAL_STORAGE)
|| permissionName.equals(permission.WRITE_EXTERNAL_STORAGE)) {
return "存储空间";
} else {
return "";
}
}
}

View File

@@ -0,0 +1,155 @@
package com.fengliyan.base.base.permission;
import android.Manifest.permission;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import java.util.ArrayList;
public class PermissionHelperActivity extends Activity {
private static final String TAG = "PermissionHelpActivity";
private ArrayList<String> mShouldRequestList = null;
private ArrayList<String> mSpecialPermissionList = null;
// 拒绝的权限
private ArrayList<String> mDeniedPermissions = new ArrayList<>();
// 拒绝的权限
private ArrayList<String> mNeverAskPermissions = new ArrayList<>();
public static final int REQUEST_CODE_WRITE_SETTING = 1;
public static final int REQUEST_CODE_ALERT_WINDOW = 2;
private PermissionDialog permissionDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, TAG + "onCreate");
if (savedInstanceState == null) {
handleRequestPermissionsIntent(getIntent());
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleRequestPermissionsIntent(intent);
}
// 权限申请
private void handleRequestPermissionsIntent(Intent intent) {
String[] permissions = intent.getStringArrayExtra("permissions");
mShouldRequestList = new ArrayList<>();
permissionDialog = new PermissionDialog(this, permissions);
permissionDialog.show();
for (String permissionName : permissions) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissionName)) {
mShouldRequestList.add(permissionName);
}
if (permission.WRITE_SETTINGS.equals(permissionName)
|| permission.SYSTEM_ALERT_WINDOW.equals(permissionName)) {
if (mSpecialPermissionList == null) {
mSpecialPermissionList = new ArrayList<>();
}
mSpecialPermissionList.add(permissionName);
}
}
int requestCode = intent.getIntExtra("requestCode", 0);
ActivityCompat.requestPermissions(this, permissions, requestCode);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (permissionDialog != null && permissionDialog.isShowing()) {
permissionDialog.dismiss();
}
}
// 返回结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
mDeniedPermissions.add(permissions[i]);
if (mShouldRequestList.contains(permissions[i])
&& !ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) {
mNeverAskPermissions.add(permissions[i]);
}
}
}
handleResult();
}
@TargetApi(VERSION_CODES.M)
private void handleResult() {
if (mSpecialPermissionList == null || mSpecialPermissionList.size() == 0) {
int requestCode = getIntent().getIntExtra("requestCode", 0);
PermissionHelper.onRequestPermissionResult(requestCode, mDeniedPermissions, mNeverAskPermissions);
finish();
} else {
String permissionName = mSpecialPermissionList.remove(mSpecialPermissionList.size() - 1);
if (permission.SYSTEM_ALERT_WINDOW.equals(permissionName)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_ALERT_WINDOW);
} else if (permission.WRITE_SETTINGS.equals(permissionName)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_WRITE_SETTING);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_WRITE_SETTING:
if (VERSION.SDK_INT >= VERSION_CODES.M) {
if (Settings.System.canWrite(this)) {
mDeniedPermissions.remove(permission.WRITE_SETTINGS);
mNeverAskPermissions.remove(permission.WRITE_SETTINGS);
} else if (!mDeniedPermissions.contains(permission.WRITE_SETTINGS)) {
mDeniedPermissions.add(permission.WRITE_SETTINGS);
}
handleResult();
}
break;
case REQUEST_CODE_ALERT_WINDOW:
if (VERSION.SDK_INT >= VERSION_CODES.M) {
if (Settings.canDrawOverlays(this)) {
mDeniedPermissions.remove(permission.SYSTEM_ALERT_WINDOW);
mNeverAskPermissions.remove(permission.SYSTEM_ALERT_WINDOW);
} else if (!mDeniedPermissions.contains(permission.SYSTEM_ALERT_WINDOW)) {
mDeniedPermissions.add(permission.SYSTEM_ALERT_WINDOW);
}
handleResult();
}
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,17 @@
package com.fengliyan.base.base.permission;
/**
* 权限请求
* Created by yangjinbo on 2016-4-29.
*/
public interface PermissionRequest {
/**
* 继续请求
*/
void proceed();
/**
* 取消请求
*/
void cancel() ;
}

View File

@@ -0,0 +1,37 @@
package com.fengliyan.base.base.permission;
/**
* 权限请求的回调
* Created by yangjinbo on 2016-4-28.
*/
public interface PermissionResultCallBack {
/**
* 当所有权限的申请被用户同意之后,该方法会被调用
*/
void onPermissionGranted();
/**
* 当权限申请中的某一个或多个权限,被用户曾经否定了
* 该方法将会被调用
*
* @param permissions 拒绝的权限
*/
void onPermissionDenied(String... permissions);
/**
* 当权限申请需要弹出让用户选择时,选择前弹出的解释说明时,该方法将会被调用.
* 如果需要停止请求,可以通过调用{@link PermissionRequest#cancel()}取消请求。
* 如果要继续请求,需要调用{@link PermissionRequest#proceed()}继续请求。
*
* @param request 权限请求
*/
void onRationalShow(PermissionRequest request);
/**
* 当用户拒绝时,并且选择了不再询问时回调
*
* @param permissions 不在询问的权限
*/
void onNeverAskAgain(String... permissions);
}

View File

@@ -0,0 +1,91 @@
package com.fengliyan.base.base.utils;
import android.os.Build;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* AES 加密工具类,目前只支持128bit加密
*
* @author yangjinbo
*/
public class AesUtil {
/**
* 加密数据方法
*
* @param seed 密钥
* @param cleartext 待加密内容
* @return 返回加密结果
*/
public static String encrypt(String seed, String cleartext) {
try {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return Utility.toHex(result);
} catch (Exception e) {
throw new RuntimeException("Failed to encrypt", e);
}
}
/**
* 解密数据
*
* @param seed 密钥
* @param encrypted 待解密内容
* @return 解密结果
*/
public static String decrypt(String seed, String encrypted) {
try {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = Utility.toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
} catch (Exception e) {
throw new RuntimeException("Failed to decrypt", e);
}
}
public static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr; // SecureRandom.getInstance("SHA1PRNG");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
public static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(clear);
}
public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return cipher.doFinal(encrypted);
}
public static String toHex(String txt) {
return Utility.toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(Utility.toByte(hex));
}
}

View File

@@ -0,0 +1,182 @@
package com.fengliyan.base.base.utils;
import android.os.Environment;
import com.fengliyan.base.base.ContextHolder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
/**
* 文件相关操作
* Created by yangjinbo on 2015/12/23.
*/
public class FileUtil {
/**
* 获取app的data内部存储的根目录
*
* @return 存储路径
*/
public static String getInternalRootDir() {
return ContextHolder.getApplicationContext().getFilesDir().getAbsolutePath()
+ File.separator + "mucfc" + File.separator;
}
public static boolean hasExtentsion(String filename) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return true;
} else {
return false;
}
}
/**
* 获取app的data内部存储的稳定存储目录存储在文件夹内的数据默认不删除。
*
* @return 存储路径
*/
public static String getInternalStableDir() {
return ContextHolder.getApplicationContext().getFilesDir().getAbsolutePath()
+ File.separator + "mucfc" + File.separator + "stable" + File.separator;
}
/**
* 获取app的SD存储的稳定存储目录存储在文件夹内的数据默认不删除。
*
* @return 存储路径
*/
public static String getExternStableDir() {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return null;
}
return Environment.getExternalStorageDirectory().getAbsoluteFile() + File.separator
+ "mucfc" + File.separator + "stable" + File.separator;
}
/**
* 获取招联金融所有应用在sdcard 目录下存储根目录,后续所有招联应用都使用此目录存储。
*
* @return sdcard的存储路径当sdcard不可用时返回null
*/
public static String getExternalRootDir() {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return null;
}
return Environment.getExternalStorageDirectory().getAbsoluteFile() + File.separator
+ "mucfc" + File.separator;
}
/**
* 获取app在sdcard 目录下存储根目录。
*
* @return sdcard的存储路径当sdcard不可用时返回null
*/
public static String getExternalAppRootDir() {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return null;
}
return Environment.getExternalStorageDirectory().getAbsoluteFile() + File.separator
+ "mucfc" + File.separator + ContextHolder.getApplicationContext().getPackageName()
+ File.separator;
}
/**
* 删除文件夹及其文件夹里面的文件
*
* @param path 文件夹
* @return true 删成功了, false未删除成功但是文件夹里面的部分内容可能已经删除。
*/
public static boolean deleteFolder(String path) {
File dir = new File(path);
if (!dir.exists() || !dir.isDirectory()) {
return false;
}
// 递归删除目录中的子目录下
String[] children = dir.list();
if (children != null) {
for (String child : children) {
File file = new File(dir, child);
if (file.isFile() && !file.delete()) {
return false;
}
if (file.isDirectory() && !deleteFolder(file.getPath())) {
return false;
}
}
}
// 目录此时为空,可以删除
return dir.delete();
}
/**
* 将文件中的内容读入到byte数组中
*
* @param fileName 文件名
* @return 文件的byte数组当文件不存在或为目录时返回的{@code null}。
* @throws IllegalArgumentException if {@code fileName} is {@code null}。
*/
public static byte[] readToByteArray(String fileName) {
if (fileName == null) {
throw new IllegalArgumentException("fileName cannot be null!");
}
File file = new File(fileName);
if (!file.exists() || file.isDirectory()) {
return null;
}
InputStream input = null;
try {
input = new FileInputStream(fileName);
byte[] buffer = new byte[(int) file.length()];
if (input.read(buffer) == -1) {
return null;
} else {
return buffer;
}
} catch (IOException e) {
return null;
} finally {
Utility.closeSilently(input);
}
}
/**
* 读取文件内容,并以字符串的形式返回
*
* @param fileName 文件名
* @return 当文件不存在或为目录时,返回的{@code null}。
* @throws IllegalArgumentException if {@code fileName} is {@code null}。
*/
public static String readFileToString(String fileName) {
if (fileName == null) {
throw new IllegalArgumentException("fileName cannot be null!");
}
File file = new File(fileName);
if (!file.exists() || file.isDirectory()) {
return null;
}
FileReader fileReader = null;
try {
fileReader = new FileReader(file);
char[] buffer = new char[(int) file.length()];
fileReader.read(buffer);
return new String(buffer);
} catch (IOException e) {
return null;
} finally {
Utility.closeSilently(fileReader);
}
}
}

View File

@@ -0,0 +1,70 @@
package com.fengliyan.base.base.utils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 压缩图片
* Created by yangjinbo on 2016/2/19.
*/
public class ImageCompressUtil {
/**
* 压缩图片
*
* @param maxSize 需要压缩的大小
* @param imageFile 图片路径
* @param deleteOriginal 是否删除原始图片,true删除,false不删除
* @return 压缩后的图片路径
*/
public static String compress(int maxSize, String imageFile, boolean deleteOriginal) {
File file = new File(imageFile);
long size = file.length();
if (size < maxSize) {
return imageFile;
}
String newImageName = null;
FileOutputStream out = null;
Bitmap bmp = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = (int) (Math.sqrt(size / maxSize) + 0.8f);
bmp = BitmapFactory.decodeFile(imageFile, options);
File newFile = File.createTempFile("tmp-", ".dat", file.getParentFile());
out = new FileOutputStream(newFile);
bmp.compress(Bitmap.CompressFormat.JPEG, 80, out);
newImageName = newFile.getAbsolutePath();
if (deleteOriginal) {
new File(imageFile).delete();
}
return newImageName;
} catch (OutOfMemoryError e) {
return imageFile;
} catch (IOException e) {
return imageFile;
} finally {
Utility.closeSilently(out);
if (bmp != null) {
bmp.recycle();
}
}
}
/**
* 压缩图片,会删除原始图片
*
* @param maxSize 需要压缩的大小
* @param imageFile 图片路径
* @return 压缩后的图片路径
*/
public static String compress(int maxSize, String imageFile) {
return compress(maxSize, imageFile, true);
}
}

View File

@@ -0,0 +1,99 @@
package com.fengliyan.base.base.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* MD5的相关操作
* Created by yangjinbo on 2015/12/23.
*/
public class Md5Util {
private static final String HASH_ALGORITHM = "MD5";
/**
* 获取文件MD5
*
* @param fileName 文件名
* @return 当文件不存在或者是目录时以及文件读取和MD5算法不存在时返回null其他返回文件MD5值
*/
public static String getFileMd5(String fileName) {
if (fileName == null) {
return null;
}
File file = new File(fileName);
if (!file.exists() || file.isDirectory()) {
return null;
}
byte[] md5 = getMD5(file);
if (md5 == null) {
return null;
}
return Utility.toHex(md5);
}
/**
* 获取字符串MD5
*
* @param text 字符串
* @return 字符串转换为16进制的Md5值。当字符串为空时或发生错误时返回null
*/
public static String getStringMd5(String text) {
if (text == null) {
return null;
}
byte[] md5 = getMD5(text.getBytes());
if (md5 == null) {
return null;
}
return Utility.toHex(md5);
}
/**
* 获取文件的MD5
*
* @param file 文件
*/
private static byte[] getMD5(File file) {
InputStream fis = null;
byte[] md5 = null;
try {
fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
int numRead;
while ((numRead = fis.read(buffer)) != -1) {
digest.update(buffer, 0, numRead);
}
md5 = digest.digest();
} catch (Exception e) {
return null;
} finally {
Utility.closeSilently(fis);
}
return md5;
}
/**
* 获取byte数组的md5
*
* @param data 数据
*/
private static byte[] getMD5(byte[] data) {
byte[] hash;
try {
MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
digest.update(data);
hash = digest.digest();
} catch (NoSuchAlgorithmException e) {
return null;
}
return hash;
}
}

View File

@@ -0,0 +1,93 @@
package com.fengliyan.base.base.utils;
import android.content.Context;
import android.content.SharedPreferences;
/**
* Created by zhangbin on 2019/2/21.
*/
public class NoClearSPUtils {
private final static String name = "no_clear_sp";
private final static int mode = Context.MODE_PRIVATE;
/**
* 保存首选项
*
* @param context
* @param key
* @param value
*/
public static void saveBoolean(Context context, String key, boolean value) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
SharedPreferences.Editor edit = sp.edit();
edit.putBoolean(key, value);
edit.commit();
}
public static void saveInt(Context context, String key, int value) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
SharedPreferences.Editor edit = sp.edit();
edit.putInt(key, value);
edit.commit();
}
public static void saveString(Context context, String key, String value) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
SharedPreferences.Editor edit = sp.edit();
edit.putString(key, value);
edit.commit();
}
/**
* 获取首选项
*
* @param context
* @param key
* @param defValue
* @return
*/
public static boolean getBoolean(Context context, String key, boolean defValue) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
return sp.getBoolean(key, defValue);
}
public static boolean getBoolean(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
return sp.getBoolean(key, false);
}
public static int getInt(Context context, String key, int defValue) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
return sp.getInt(key, defValue);
}
public static int getInt(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
return sp.getInt(key, 0);
}
public static String getString(Context context, String key, String defValue) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
return sp.getString(key, defValue);
}
public static String getString(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
return sp.getString(key, "");
}
/**
* 清除保存
*
* @param context
*/
public static void clear(Context context) {
SharedPreferences sp = context.getSharedPreferences(name, mode);
SharedPreferences.Editor editor = sp.edit();
editor.clear();
editor.commit();
}
}

View File

@@ -0,0 +1,334 @@
package com.fengliyan.base.base.utils;
import android.app.Notification;
import android.content.AsyncQueryHandler;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class NotificationBadgesUtils {
/**
* 应用角标工具类
*/
private static int notificationId = 0;
public static boolean setCount(final int count, final Context context) {
if (count >= 0 && context != null) {
Log.d("BRAND", Build.BRAND);
Log.v("-=-", "角标数量" + count);
Log.v("-=-", "Build.BRAND.toLowerCase()" + Build.BRAND.toLowerCase());
switch (Build.BRAND.toLowerCase()) {
case "xiaomi":
case "redmi":
// new Handler().postDelayed(new Runnable() {
// @Override
// public void run() {
// setNotificationBadge(count, context);
// }
// }, 3000);
setXiaomiBadge(count);
return true;
case "huawei":
return setHuaweiBadge(count, context);
case "honor":
return setHonorBadge(count, context);
case "samsung":
return setSamsungBadge(count, context);
case "oppo":
return setOPPOBadge(count, context) || setOPPOBadge2(count, context);
case "vivo":
return setVivoBadge(count, context);
case "lenovo":
return setZukBadge(count, context);
case "htc":
return setHTCBadge(count, context);
case "sony":
return setSonyBadge(count, context);
// default:
// return setNotificationBadge(count, context);
}
return true;
} else {
return false;
}
}
// public static boolean setNotificationBadge(int count, Context context) {
// NotificationManager notificationManager = (NotificationManager) context.getSystemService
// (Context.NOTIFICATION_SERVICE);
// if (notificationManager == null) {
// return false;
// }
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// // 8.0之后添加角标需要NotificationChannel
// NotificationChannel channel = new NotificationChannel("badge", "badge",
// NotificationManager.IMPORTANCE_DEFAULT);
// channel.setShowBadge(true);
// notificationManager.createNotificationChannel(channel);
// }
// Intent intent = new Intent(context, MainActivity.class);
// PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Notification notification = new NotificationCompat.Builder(context, "badge")
// .setContentTitle(context.getResources().getString(R.string.application_angle))
// .setContentText(context.getResources().getString(R.string.you_have) + count + context.getResources().getString(R.string.unread_message))
// .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap
// .ic_launcher))
// .setSmallIcon(R.mipmap.ic_launcher)
// .setAutoCancel(true)
// .setContentIntent(pendingIntent)
// .setChannelId("badge")
// .setNumber(count)
// .setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL).build();
// // 小米
// if (Build.BRAND.equalsIgnoreCase("xiaomi")) {
// setXiaomiBadge(count);
// }
// notificationManager.notify(notificationId++, notification);
// return true;
// }
private static void setXiaomiBadge(int count) {
try {
Notification notification = new Notification();
Field field = notification.getClass().getDeclaredField("extraNotification");
Object extraNotification = field.get(notification);
Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int
.class);
method.invoke(extraNotification, count);
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean setHonorBadge(int count, Context context) {
try {
String launchClassName = getLauncherClassName(context);
if (TextUtils.isEmpty(launchClassName)) {
return false;
}
Bundle bundle = new Bundle();
bundle.putString("package", context.getPackageName());
bundle.putString("class", launchClassName);
bundle.putInt("badgenumber", count);
context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher" +
".settings/badge/"), "change_badge", null, bundle);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean setHuaweiBadge(int count, Context context) {
try {
String launchClassName = getLauncherClassName(context);
if (TextUtils.isEmpty(launchClassName)) {
return false;
}
Bundle bundle = new Bundle();
bundle.putString("package", context.getPackageName());
bundle.putString("class", launchClassName);
bundle.putInt("badgenumber", count);
context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher" + ".settings/badge/"), "change_badge", null, bundle);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean setSamsungBadge(int count, Context context) {
try {
String launcherClassName = getLauncherClassName(context);
if (TextUtils.isEmpty(launcherClassName)) {
return false;
}
Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");
intent.putExtra("badge_count", count);
intent.putExtra("badge_count_package_name", context.getPackageName());
intent.putExtra("badge_count_class_name", launcherClassName);
context.sendBroadcast(intent);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Deprecated
private static boolean setOPPOBadge(int count, Context context) {
try {
Bundle extras = new Bundle();
extras.putInt("app_badge_count", count);
context.getContentResolver().call(Uri.parse("content://com.android.badge/badge"),
"setAppBadgeCount", String.valueOf(count), extras);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Deprecated
private static boolean setOPPOBadge2(int count, Context context) {
try {
Intent intent = new Intent("com.oppo.unsettledevent");
intent.putExtra("packageName", context.getPackageName());
intent.putExtra("number", count);
intent.putExtra("upgradeNumber", count);
PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> receivers = packageManager.queryBroadcastReceivers(intent, 0);
if (receivers != null && receivers.size() > 0) {
context.sendBroadcast(intent);
} else {
Bundle extras = new Bundle();
extras.putInt("app_badge_count", count);
context.getContentResolver().call(Uri.parse("content://com.android.badge/badge"),
"setAppBadgeCount", null, extras);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean setVivoBadge(int count, Context context) {
try {
String launcherClassName = getLauncherClassName(context);
if (TextUtils.isEmpty(launcherClassName)) {
return false;
}
Intent intent = new Intent("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM");
intent.putExtra("packageName", context.getPackageName());
intent.putExtra("className", launcherClassName);
intent.putExtra("notificationNum", count);
context.sendBroadcast(intent);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean setZukBadge(int count, Context context) {
try {
Bundle extra = new Bundle();
ArrayList<String> ids = new ArrayList<>();
// 以列表形式传递快捷方式id可以添加多个快捷方式id
// ids.add("custom_id_1");
// ids.add("custom_id_2");
extra.putStringArrayList("app_shortcut_custom_id", ids);
extra.putInt("app_badge_count", count);
Uri contentUri = Uri.parse("content://com.android.badge/badge");
Bundle bundle = context.getContentResolver().call(contentUri, "setAppBadgeCount", null,
extra);
return bundle != null;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean setHTCBadge(int count, Context context) {
try {
ComponentName launcherComponentName = getLauncherComponentName(context);
if (launcherComponentName == null) {
return false;
}
Intent intent1 = new Intent("com.htc.launcher.action.SET_NOTIFICATION");
intent1.putExtra("com.htc.launcher.extra.COMPONENT", launcherComponentName
.flattenToShortString());
intent1.putExtra("com.htc.launcher.extra.COUNT", count);
context.sendBroadcast(intent1);
Intent intent2 = new Intent("com.htc.launcher.action.UPDATE_SHORTCUT");
intent2.putExtra("packagename", launcherComponentName.getPackageName());
intent2.putExtra("count", count);
context.sendBroadcast(intent2);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean setSonyBadge(int count, Context context) {
String launcherClassName = getLauncherClassName(context);
if (TextUtils.isEmpty(launcherClassName)) {
return false;
}
try {
//官方给出方法
ContentValues contentValues = new ContentValues();
contentValues.put("badge_count", count);
contentValues.put("package_name", context.getPackageName());
contentValues.put("activity_name", launcherClassName);
SonyAsyncQueryHandler asyncQueryHandler = new SonyAsyncQueryHandler(context
.getContentResolver());
asyncQueryHandler.startInsert(0, null, Uri.parse("content://com.sonymobile.home" +
".resourceprovider/badge"), contentValues);
return true;
} catch (Exception e) {
try {
//网上大部分使用方法
Intent intent = new Intent("com.sonyericsson.home.action.UPDATE_BADGE");
intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", count > 0);
intent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME",
launcherClassName);
intent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", String
.valueOf(count));
intent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", context
.getPackageName());
context.sendBroadcast(intent);
return true;
} catch (Exception e1) {
e1.printStackTrace();
return false;
}
}
}
private static String getLauncherClassName(Context context) {
ComponentName launchComponent = getLauncherComponentName(context);
if (launchComponent == null) {
return "";
} else {
return launchComponent.getClassName();
}
}
private static ComponentName getLauncherComponentName(Context context) {
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context
.getPackageName());
if (launchIntent != null) {
return launchIntent.getComponent();
} else {
return null;
}
}
static class SonyAsyncQueryHandler extends AsyncQueryHandler {
SonyAsyncQueryHandler(ContentResolver cr) {
super(cr);
}
}
}

View File

@@ -0,0 +1,209 @@
package com.fengliyan.base.base.utils;
import android.text.TextUtils;
import android.util.Base64;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
/**
* RSA加密方式
*/
public class RsaUtil {
// 公钥
public static final String PUBLIC_KEY = "PublicKey";
// 私钥
public static final String PRIVATE_KEY = "PrivateKey";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
private static final int KEY_LENGTH = 256;
/**
* 字符串加密
*
* @param clearText
* @param publicKey
* @return 返回密文的BASE64字符串
*/
public static String encryptByPublicKey(String clearText, String publicKey) {
if (null == clearText) {
throw new IllegalArgumentException("clearText cannot be null");
}
try {
byte[] clearBytes = clearText.getBytes("UTF-8");
byte[] encryptBytes = encryptByPublicKey(clearBytes, publicKey);
return new String(Base64.encode(encryptBytes, Base64.DEFAULT), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Failed to encrypt with public key", e);
}
}
/**
* 加密数据
*
* @param data 加密内容
* @param publicKey 加密公钥
* @return 加密后的结果
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey) {
if (null == data) {
throw new IllegalArgumentException("data cannot be null");
}
if (TextUtils.isEmpty(publicKey)) {
throw new IllegalArgumentException("publicKey cannot be null or empty");
}
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] bytePublicKey = Base64.decode(publicKey, Base64.DEFAULT);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(bytePublicKey);
Key publicK = keyFactory.generatePublic(x509EncodedKeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); //Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
return encryptedData;
} finally {
out.close();
}
} catch (Exception e) {
throw new RuntimeException("Failed to encrypt with public key", e);
}
}
/**
* BASE64密文解密
*
* @param encryptedBase64Text BASE64编码的密文
* @param privateKey
* @return
*/
public static String decryptByPrivateKey(String encryptedBase64Text, String privateKey) {
if (null == encryptedBase64Text) {
throw new IllegalArgumentException("encryptedBase64Text cannot be null");
}
try {
byte[] encryptedBytes = Base64.decode(encryptedBase64Text.getBytes("UTF-8"), Base64.DEFAULT);
byte[] clearBytes = decryptByPrivateKey(encryptedBytes, privateKey);
return new String(clearBytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Failed to decrypt with private key", e);
}
}
/**
* 解密内容
*
* @param encryptedData 待解密数据
* @param privateKey 私钥
* @return 解密后的结果
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) {
if (null == encryptedData) {
throw new IllegalArgumentException("encryptedData cannot be null");
}
if (TextUtils.isEmpty(privateKey)) {
throw new IllegalArgumentException("privateKey cannot be null or empty");
}
try {
byte[] keyBytes = Base64.decode(privateKey, Base64.DEFAULT);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");//Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher
.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher
.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
return decryptedData;
} finally {
out.close();
}
} catch (Exception e) {
throw new RuntimeException("Failed to decrypt with private key", e);
}
}
public static Map<String, String> getGenKeyPair() {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.generateKeyPair();
byte[] pubKeyBytes = Base64.encode(keyPair.getPublic().getEncoded(), Base64.DEFAULT);
byte[] priKeyBytes = Base64.encode(keyPair.getPrivate().getEncoded(), Base64.DEFAULT);
Map<String, String> map = new HashMap<>();
map.put(PUBLIC_KEY, new String(pubKeyBytes));
map.put(PRIVATE_KEY, new String(priKeyBytes));
return map;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}

View File

@@ -0,0 +1,118 @@
package com.fengliyan.base.base.utils;
import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import java.io.Closeable;
import java.lang.reflect.Method;
import java.util.Random;
/**
* 存放一些小的较独立的方法
* Created by yangjinbo on 2015/12/25.
*/
public class Utility {
/**
* 关闭资源,不抛出异常
*
* @param closeable 待关闭资源
*/
public static void closeSilently(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception ignored) {
}
}
}
/**
* 检查权限是否同意
* @param permission 权限名称
* @return true 具有该权限
*/
public static boolean checkPermission(Context context, String permission) {
return context.getPackageManager().checkPermission(permission, context.getPackageName()) == PackageManager
.PERMISSION_GRANTED;
}
/**
* 获取随机字符串
* @param length 字符串长度
* @return 随机字符串
*/
public static String getRandomString(int length) {
if(length < 0) {
throw new IllegalArgumentException("The length cannot be a negative!");
}
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
/**
* 将16进制字符串转为byte数组
*
* @param hexString 待转数组
* @return byte数组
*/
public static byte[] toByte(String hexString) {
if (hexString == null) {
return null;
}
int len = hexString.length() / 2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++) {
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
}
return result;
}
/**
* 将byte数组转为16进制字符串
*
* @param buf 待转数组
*/
public static String toHex(byte[] buf) {
if (buf == null) {
return "";
}
StringBuffer result = new StringBuffer(2 * buf.length);
for (byte b : buf) {
appendHex(result, b);
}
return result.toString();
}
private final static String HEX = "0123456789abcdef";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
/**
* 获取系统的prop属性
* @param key 属性的key
* @return 属性值
*/
public static String getSystemProperties(Context context, String key) {
if (TextUtils.isEmpty(key)) {
return null;
}
try {
Class SystemProperties = context.getClassLoader().loadClass("android.os.SystemProperties");
Method get = SystemProperties.getMethod("get", String.class);
return (String) get.invoke(null, key);
} catch (Exception e) {
return null;
}
}
}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:orientation="vertical"
tools:viewBindingIgnore="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="15dp"
android:background="#cdcdcd"
android:gravity="center_vertical"
android:minHeight="70dp"
android:orientation="vertical"
android:padding="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="设备权限使用说明"
android:textColor="#333333"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_permission"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="用于识别设备,进行信息推送和安全保障等功能"
android:textColor="#333333"
android:textSize="14dp" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Base</string>
</resources>

View File

@@ -0,0 +1,17 @@
package com.fengliyan.base;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}