Skip to content

Commit 5ed0d2d

Browse files
committedMar 4, 2020
【头像信息修改完善(相机、选图、动态权限初步完成)】
ui下新建一个camera包(用于处理照片),下新建一个CameraHandler、XiaoYunCamera、RequestCodes、CameraImageBean;(后面移动到core/ui) core下引入uCrop库、权限库PermissionsDispatcher、工具库AndroidUtilCode; Camera包转移到core/ui下(相关文件、依赖库同); Drawable、layout、style、anim文件也移动过去(具体移动的文件目录见项目文档); core/res下,新建,anim下push_bottom_in.xml、push_bottom_out.xml;drawable下新建btn_border.xml、btn_border_nativephoto.xml、btn_border_takephoto.xml;layout下dialog_camera_panel.xml; 更新Configurator、PermissionCheckerDelegate、FileUtil(注释)、style、AndroidManifest(权限声明)、UserProfileClickListener、UserProfileDelegate、PersonalDelegate
1 parent 94a3c5e commit 5ed0d2d

31 files changed

+603
-19
lines changed
 
Binary file not shown.
0 Bytes
Binary file not shown.

‎xiaoyun_core/build.gradle

+9
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,13 @@ dependencies {
120120

121121
// 引入multidex库
122122
implementation 'com.android.support:multidex:1.0.3'
123+
124+
//工具包
125+
implementation 'com.blankj:utilcode:1.7.1'
126+
//动态权限处理
127+
api 'com.github.hotchemi:permissionsdispatcher:3.0.1'
128+
annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:3.0.1'
129+
//图片剪裁
130+
implementation 'com.github.yalantis:ucrop:2.2.1-native'
123131
}
132+

‎xiaoyun_core/src/main/AndroidManifest.xml

+21-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,27 @@
33
xmlns:tools="http://schemas.android.com/tools"
44
package="com.lwp.xiaoyun_core">
55

6-
<uses-permission android:name="android.permission.INTERNET"/>
6+
<!--网络权限-->
7+
<uses-permission android:name="android.permission.INTERNET" />
8+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
9+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
10+
11+
<!--拨号权限-->
12+
<uses-permission android:name="android.permission.CALL_PHONE" />
13+
14+
<!--文件权限-->
15+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
16+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
17+
18+
<!--相机权限-->
19+
<uses-permission android:name="android.permission.VIBRATE" />
20+
<uses-permission android:name="android.permission.CAMERA" />
21+
22+
<uses-feature android:name="android.hardware.camera" />
23+
<uses-feature android:name="android.hardware.camera.autofocus" />
24+
25+
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
26+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
727

828
<application
929
android:allowBackup="true"

‎xiaoyun_core/src/main/java/com/lwp/xiaoyun_core/app/Configurator.java

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.os.Handler;
55
import android.support.annotation.NonNull;
66

7+
import com.blankj.utilcode.util.Utils;
78
import com.joanzapata.iconify.IconFontDescriptor;
89
import com.joanzapata.iconify.Iconify;
910
import com.lwp.xiaoyun_core.delegates.web.event.Event;
@@ -127,6 +128,7 @@ public final Configurator withWebHost(String host) {
127128
public final void configure() {
128129
initIcons();//字体图标库是非常通用的,写在这里保证初始化完成时图标库也初始化完成
129130
XIAOYUN_CONFIGS.put(ConfigKeys.CONFIG_READY, true);
131+
Utils.init(XiaoYun.getApplicationContext());//初始化工具包库
130132
}
131133

132134

‎xiaoyun_core/src/main/java/com/lwp/xiaoyun_core/delegates/PermissionCheckerDelegate.java

+84
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
package com.lwp.xiaoyun_core.delegates;
22

3+
import android.Manifest;
4+
import android.content.DialogInterface;
5+
import android.support.annotation.NonNull;
6+
import android.support.v7.app.AlertDialog;
7+
import android.widget.Toast;
8+
9+
import com.lwp.xiaoyun_core.ui.camera.XiaoYunCamera;
10+
11+
import permissions.dispatcher.NeedsPermission;
12+
import permissions.dispatcher.OnNeverAskAgain;
13+
import permissions.dispatcher.OnPermissionDenied;
14+
import permissions.dispatcher.OnShowRationale;
15+
import permissions.dispatcher.PermissionRequest;
16+
import permissions.dispatcher.RuntimePermissions;
17+
318
/**
419
* <pre>
520
* author : 李蔚蓬(简书_凌川江雪)
@@ -8,5 +23,74 @@
823
* 用来进行(基于Android 6.0之后的动态权限)权限的判定
924
* </pre>
1025
*/
26+
//Register an Activity or Fragment to handle permissions 在框架中注册一个需要处理权限的活动或者碎片
27+
@RuntimePermissions
1128
public abstract class PermissionCheckerDelegate extends BaseDelegate {
29+
30+
//本方法不是 直接拿来调用的,是用来生成代码的
31+
// (这里具体实现,在 生成类PermissionCheckerDelegatePermissionsDispatcher中 抽象调用)
32+
// 动态申请权限成功后,执行本方法
33+
// .
34+
// 所以它不能是private static,否则annotationProcessor或者注解 没办法正常读取解析
35+
//@NeedsPermission注解的意义:
36+
// Annotate a method which performs the action that requires one or more permissions
37+
// 注释执行需要一个或多个权限的操作的方法
38+
@NeedsPermission({Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
39+
void startCamera() {
40+
// 动态申请权限(相机、读写)成功后!!! 执行本方法!!!
41+
XiaoYunCamera.start(this);
42+
}
43+
44+
//开始请求权限
45+
public void startCameraWithCheck() {
46+
//开始请求权限(相机、读写)
47+
PermissionCheckerDelegatePermissionsDispatcher.startCameraWithPermissionCheck(this);
48+
}
49+
50+
//注解在当用户拒绝了权限请求时需要调用的方法上
51+
@OnPermissionDenied({Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
52+
void onCameraDenied() {
53+
Toast.makeText(getContext(), "不允许拍照", Toast.LENGTH_LONG).show();
54+
}
55+
56+
//注解在当用户选中了 授权窗口中的 不再询问复选框 后 并拒绝了权限请求时需要调用的方法,
57+
// 一般可以向用户解释 为何申请此权限,并根据 实际需求 决定 是否再次弹出权限请求对话框
58+
@OnNeverAskAgain({Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
59+
void onCameraNever() {
60+
Toast.makeText(getContext(), "拒绝使用相机,不再询问,下次使用请在系统设置", Toast.LENGTH_LONG).show();
61+
}
62+
63+
//注解在用于向用户解释为什么需要调用该权限的方法上,
64+
//只有当第一次请求权限被用户拒绝,下次请求权限之前会调用
65+
@OnShowRationale({Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
66+
void onCameraRationale(PermissionRequest request) {
67+
showRationaleDialog(request);
68+
}
69+
private void showRationaleDialog(final PermissionRequest request) {
70+
new AlertDialog.Builder(getContext())
71+
.setPositiveButton("同意", new DialogInterface.OnClickListener() {
72+
@Override
73+
public void onClick(DialogInterface dialog, int which) {
74+
request.proceed();
75+
}
76+
})
77+
.setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
78+
@Override
79+
public void onClick(DialogInterface dialog, int which) {
80+
request.cancel();
81+
}
82+
})
83+
.setCancelable(false)
84+
.setMessage("更新头像需要使用相机或者访问本地相册喔~\n上次被您拒绝了,现在麻烦同意一下权限可以嘛老铁?")
85+
.show();
86+
}
87+
88+
//请求权限的结果处理
89+
@Override
90+
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
91+
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
92+
93+
//PermissionCheckerDelegatePermissionsDispatcher 是注解自动生成的!!
94+
PermissionCheckerDelegatePermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
95+
}
1296
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package com.lwp.xiaoyun_core.ui.camera;
2+
3+
import android.content.ContentValues;
4+
import android.content.Intent;
5+
import android.graphics.Color;
6+
import android.graphics.drawable.ColorDrawable;
7+
import android.net.Uri;
8+
import android.os.Build;
9+
import android.provider.MediaStore;
10+
import android.support.v7.app.AlertDialog;
11+
import android.view.Gravity;
12+
import android.view.View;
13+
import android.view.Window;
14+
import android.view.WindowManager;
15+
16+
import com.blankj.utilcode.util.FileUtils;
17+
import com.lwp.xiaoyun_core.R;
18+
import com.lwp.xiaoyun_core.delegates.PermissionCheckerDelegate;
19+
import com.lwp.xiaoyun_core.util.file.FileUtil;
20+
21+
import java.io.File;
22+
23+
/**
24+
* <pre>
25+
* author : 李蔚蓬(简书_凌川江雪)
26+
* time : 2020/3/2 5:36
27+
* desc : 照片处理类
28+
* </pre>
29+
*/
30+
public class CameraHandler implements View.OnClickListener {
31+
32+
private final AlertDialog DIALOG;
33+
private final PermissionCheckerDelegate DELEGATE;
34+
35+
public CameraHandler(PermissionCheckerDelegate delegate) {
36+
this.DELEGATE = delegate;
37+
DIALOG = new AlertDialog.Builder(delegate.getContext()).create();
38+
}
39+
40+
//弹出Dialog弹框 内容:三个按钮,拍照 选图 取消
41+
final void beginCameraDialog() {
42+
DIALOG.show();
43+
44+
final Window window = DIALOG.getWindow();
45+
if (window != null) {
46+
window.setContentView(R.layout.dialog_camera_panel);//设置弹框布局
47+
window.setGravity(Gravity.BOTTOM);
48+
window.setWindowAnimations(R.style.anim_panel_up_from_bottom);
49+
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
50+
51+
//设置属性
52+
final WindowManager.LayoutParams params = window.getAttributes();
53+
params.width = WindowManager.LayoutParams.MATCH_PARENT;
54+
params.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
55+
params.dimAmount = 0.5f;//设置幕布黑暗程度
56+
window.setAttributes(params);
57+
58+
//设置弹框中 组件的监听
59+
window.findViewById(R.id.photodialog_btn_cancel).setOnClickListener(this);//取消按钮
60+
window.findViewById(R.id.photodialog_btn_take).setOnClickListener(this);//拍照按钮
61+
window.findViewById(R.id.photodialog_btn_native).setOnClickListener(this);//本地按钮
62+
}
63+
}
64+
65+
private String getPhotoName() {
66+
//获取一个 模板格式化后的 文件名(模板:文件头_当前时间.后缀)
67+
return FileUtil.getFileNameByTime("IMG", "jpg");
68+
}
69+
//拍照取图
70+
public void takePhoto() {
71+
final String currentPhotoName = getPhotoName();
72+
//拍照意图
73+
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
74+
//File 临时文件句柄 临时文件:这里是系统相册目录下的当前文件名的文件临时句柄
75+
//CAMERA_PHOTO_DIR 系统相册目录
76+
final File tempFile = new File(FileUtil.CAMERA_PHOTO_DIR, currentPhotoName);
77+
78+
//兼容7.0及以上的写法
79+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
80+
final ContentValues contentValues = new ContentValues(1);
81+
contentValues.put(MediaStore.Images.Media.DATA, tempFile.getPath());
82+
//使用 ContentProvider 的方式
83+
final Uri uri = DELEGATE.getContext().getContentResolver().
84+
insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
85+
86+
//需要讲Uri路径转化为实际路径
87+
final File realFile =
88+
FileUtils.getFileByPath(FileUtil.getRealFilePath(DELEGATE.getContext(), uri));
89+
90+
final Uri realUri = Uri.fromFile(realFile);
91+
CameraImageBean.getInstance().setPath(realUri);
92+
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
93+
} else {
94+
95+
final Uri fileUri = Uri.fromFile(tempFile);
96+
CameraImageBean.getInstance().setPath(fileUri);
97+
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
98+
}
99+
100+
//使用startActivityForResult()的形式 启动Activity
101+
DELEGATE.startActivityForResult(intent, RequestCodes.TAKE_PHOTO);
102+
}
103+
104+
//本地取图
105+
private void pickPhoto() {
106+
final Intent intent = new Intent();
107+
intent.setType("image/*");//所有的Image类型
108+
intent.setAction(Intent.ACTION_GET_CONTENT);//获取内容
109+
intent.addCategory(Intent.CATEGORY_OPENABLE);
110+
111+
//使用startActivityForResult()的形式 启动Activity
112+
// createChooser 创建选择器
113+
DELEGATE.startActivityForResult
114+
(Intent.createChooser(intent, "选择获取图片的方式"), RequestCodes.PICK_PHOTO);
115+
}
116+
117+
118+
@Override
119+
public void onClick(View v) {
120+
int id = v.getId();
121+
122+
if (id == R.id.photodialog_btn_cancel) {
123+
DIALOG.cancel();
124+
} else if (id == R.id.photodialog_btn_take) {
125+
//拍照取图
126+
takePhoto();
127+
DIALOG.cancel();
128+
} else if (id == R.id.photodialog_btn_native) {
129+
//本地取图
130+
pickPhoto();
131+
DIALOG.cancel();
132+
}
133+
}
134+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.lwp.xiaoyun_core.ui.camera;
2+
3+
import android.net.Uri;
4+
5+
/**
6+
* <pre>
7+
* author : 李蔚蓬(简书_凌川江雪)
8+
* time : 2020/3/2 5:39
9+
* desc : 存储中间值
10+
* </pre>
11+
*/
12+
public final class CameraImageBean {
13+
14+
private Uri mPath = null;
15+
16+
//单例模式
17+
private static final CameraImageBean INSTANCE = new CameraImageBean();
18+
public static CameraImageBean getInstance(){
19+
return INSTANCE;
20+
}
21+
22+
public Uri getPath() {
23+
return mPath;
24+
}
25+
26+
public void setPath(Uri mPath) {
27+
this.mPath = mPath;
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.lwp.xiaoyun_core.ui.camera;
2+
3+
4+
import com.yalantis.ucrop.UCrop;
5+
6+
/**
7+
* <pre>
8+
* author : 李蔚蓬(简书_凌川江雪)
9+
* time : 2020/3/2 5:38
10+
* desc : 请求码存储
11+
* </pre>
12+
*/
13+
public class RequestCodes {
14+
public static final int TAKE_PHOTO = 4;//拍照
15+
public static final int PICK_PHOTO = 5;//选择图片
16+
public static final int CROP_PHOTO = UCrop.REQUEST_CROP;//剪裁
17+
public static final int CROP_ERROR = UCrop.RESULT_ERROR;//剪裁错误
18+
public static final int SCAN = 7;//扫描二维码
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.lwp.xiaoyun_core.ui.camera;
2+
3+
import android.net.Uri;
4+
5+
import com.lwp.xiaoyun_core.delegates.PermissionCheckerDelegate;
6+
import com.lwp.xiaoyun_core.util.file.FileUtil;
7+
8+
/**
9+
* <pre>
10+
* author : 李蔚蓬(简书_凌川江雪)
11+
* time : 2020/3/2 5:37
12+
* desc : 照相机功能模块函数调用等
13+
* </pre>
14+
*/
15+
public class XiaoYunCamera {
16+
17+
//需要剪裁的文件
18+
public static Uri createCropFile() {
19+
return Uri.parse(FileUtil.createFile("crop_image",
20+
FileUtil.getFileNameByTime("IMG", "jpg")).getPath());
21+
}
22+
23+
public static void start(PermissionCheckerDelegate delegate) {
24+
new CameraHandler(delegate).beginCameraDialog();//弹出Dialog弹框 内容:三个按钮,拍照 选图 取消
25+
}
26+
}

0 commit comments

Comments
 (0)
Please sign in to comment.