实现思维路径:

以进入相机拍照的思维路线为例子:

1.进入app

2.判断之前是否保存头像,如果有就显示历史图像 (下面代码中在getOldAvatar();方法中执行这个逻辑)

3.点击更换图像的Button或者布局,启动对话框(下面代码中在dialogueBox();方法执行这个逻辑)

4.系统版本判断授权方式(静态还是动态授权),判断之前是否已经授权 (setPermissions(Permissions_CAMERA_KEY);这个方法执行授权逻辑)

5.如果是首次授权,就执行首次授权完成后马上运行的回调方法 onRequestPermissionsResult

5.判断完成不管是否是首次授权还是之前就是授权过了都要执行enterCamera();方法启动相机并且发送携带数据的请求

6.启动相机完成后,并且拍照完成退出相机,都要运行Intent返回数据请求回调方法onActivityResult。将传入的数据传入到cropPhoto(data.getData());方法里去执行图片剪裁。

7.在cropPhoto方法里将携带数据跳转到裁剪界面中裁剪图片,裁剪完成后又要回到onActivityResult回调方法里,执行裁剪完的数据回调工作。

8.在onActivityResult回调方法里,裁剪完的图片将运行setPicToView 方法保存图片。保存的图片将在下次启动activity时作为历史头像调用。

package com.example.lenovo.mydemoapp;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.Manifest; import com.example.lenovo.mydemoapp.myAppCompatActivity.MyAppCompatAcitivity;
import com.example.lenovo.mydemoapp.myLayout.TitleLayout; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List; public class PersonalDataModification extends AppCompatActivity{
private static final String TAG = "PDM";
private TitleLayout mTitleLayout;
private TextView mTitleText;
private LinearLayout mPersonalDataModification_Avatar,mDialog_CameraButton,mDialog_GalleryButton;
private ImageView mPersonalDataModification_imageView_Avatar;
//得到外部存储根目录路径
private String mAvatarPath = Environment.getExternalStorageDirectory() + "/myAvatar/";
private String mAvatarName = "Avatar.jpg";
private Bitmap mBitmap;
/*
进入相册,相机,照片裁剪的key组
*/
private static final int ENTER_GALLERY = 1;
private static final int ENTER_CAMERA = 2;
private static final int ENTER_CROP_PHOTO = 3;
//需要在进入相机拍照或者相册选择图像中做区分。所以写了一个KEY来处理不同的Button
private static final int Permissions_GALLERY_KEY = 1;
private static final int Permissions_CAMERA_KEY = 2;
//需要的权限 注意请不要将数组写成 private String mPermissions[] = {"Manifest.permission.WRITE_EXTERNAL_STORAGE"};
//这样加了引号的是错误的
private String mPermissions[] = {Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
setContentView(R.layout.activity_personal_data_modification);
// 设置标题栏
setTitle();
//显示历史头像
getOldAvatar();
// 添加对话框
dialogueBox();
}
/*
对话框
*/
public void dialogueBox(){
mPersonalDataModification_Avatar = (LinearLayout)findViewById(R.id.PersonalDataModification_Avatar);
mPersonalDataModification_Avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//添加对话框
AlertDialog.Builder builder = new AlertDialog.Builder(PersonalDataModification.this);
//创建对话框 注意一定要这样写 在下面的dialog才能执行dismiss();方法
final AlertDialog dialog = builder.create();
View view = LayoutInflater.from(getBaseContext()).inflate(R.layout.dialog_layout,null,false);
//导入视图
dialog.setView(view);
mDialog_CameraButton = (LinearLayout)view.findViewById(R.id.PersonalDataModification_Dialog_CameraButton);
mDialog_GalleryButton = (LinearLayout)view.findViewById(R.id.PersonalDataModification_Dialog_GalleryButton);
//相机
mDialog_CameraButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//设置权限
setPermissions(Permissions_CAMERA_KEY);
//关闭对话框
dialog.dismiss();
}
});
//相册
mDialog_GalleryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setPermissions(Permissions_GALLERY_KEY);
dialog.dismiss();
}
});
//创建并且显示
dialog.show();
}
});
}
public void setPermissions(int mPermissions_KEY){
/*
要添加List原因是想判断数组里如果有个别已经授权的权限,就不需要再添加到List中。添加到List中的权限后续将转成数组去申请权限
*/
List<String> permissionsList = new ArrayList<>();
//判断系统版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int i = 0; i < mPermissions.length; i++) {
//判断一个权限是否已经允许授权,如果没有授权就会将单个未授权的权限添加到List里面
if (ContextCompat.checkSelfPermission(this.getApplicationContext(), mPermissions[i]) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(mPermissions[i]);
}
}
//判断List不是空的,如果有内容就运行获取权限
if (!permissionsList.isEmpty()) {
String [] permissions = permissionsList.toArray(new String[permissionsList.size()]);
for (int j=0;j<permissions.length;j++){
Log.e(TAG,permissions[j]);
}
Log.e(TAG,"需要授权的权限有:"+permissions.length+"条");
//执行授权的代码。此处执行后会弹窗授权
ActivityCompat.requestPermissions(this, permissions, mPermissions_KEY);
} else { //如果是空的说明全部权限都已经授权了,就不授权了,直接执行进入相机或者图库
switch (mPermissions_KEY) {
case Permissions_CAMERA_KEY:
enterCamera();
break;
case Permissions_GALLERY_KEY:
enterGallery();
break;
default:
break;
}
}
}else {
Toast.makeText(getBaseContext(), "6.0以下的版本无需授权", Toast.LENGTH_SHORT).show();
Log.e(TAG,"6.0以下的版本无需授权");
switch (mPermissions_KEY) {
case Permissions_CAMERA_KEY:
enterCamera();
break;
case Permissions_GALLERY_KEY:
enterGallery();
break;
default:
break;
}
}
}
/*
授权完成后马上会运行的回调方法,此处写入首次授权完成后,要运行的内容
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == Permissions_CAMERA_KEY) {
if (grantResults.length > 0) { //安全写法,如果小于0,肯定会出错了
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "全部权限都成功授权进入相机");
enterCamera();
} else {
finish();
Toast.makeText(getBaseContext(), "授权失败", Toast.LENGTH_SHORT).show();
Log.e(TAG, "相机授权失败");
}
}
}
} else if (requestCode == Permissions_GALLERY_KEY) {
if (requestCode == Permissions_GALLERY_KEY) {
if (grantResults.length > 0) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "全部权限都成功授权进入相册");
enterGallery();
} else {
finish();
Toast.makeText(getBaseContext(), "授权失败", Toast.LENGTH_SHORT).show();
Log.e(TAG, "相册授权失败");
}
}
}
}
}
}
/*
点击后进入相机
*/
public void enterCamera(){
//MediaStore 多媒体存储 ACTION行动 IMAGE 图片 CAPTURW捕获
Intent intentGallery = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
/* 多媒体存储,额外制造 从文件里获取路径(获取外部存储目录 图片名称head.jpg)
将图片设置名称并且保存到外部存储空间里
*/
intentGallery.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(Environment.getExternalStorageDirectory(), mAvatarName)));
//跳转页面启动相册,携带数据请求码
startActivityForResult(intentGallery,ENTER_CAMERA);
}
/*
点击后进入相册
*/
public void enterGallery(){
Intent intentCamera = new Intent(Intent.ACTION_PICK,null);
//设置数据和类型 多媒体存储.图片.媒体.外部.内容.URI image/*图片格式
intentCamera.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");
startActivityForResult(intentCamera, ENTER_GALLERY); }
/*
从Intent中返回请求数据的方法,活动退出后运行这个方法
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
/*
相册选中图片后的数据回调
*/
case ENTER_GALLERY:
if(resultCode == RESULT_OK){
cropPhoto(data.getData());
}
break;
/*
拍照完成后的数据回调
*/
case ENTER_CAMERA:
if (resultCode == RESULT_OK) {
File temp = new File(Environment.getExternalStorageDirectory() + "/"+mAvatarName);
cropPhoto(Uri.fromFile(temp));// 裁剪图片 cropPhoto 200行方法
}
break;
/*
裁剪完成后的数据回调
*/
case ENTER_CROP_PHOTO:
if (data.resolveActivity(getPackageManager())!=null) {//判断Intent是否为空
Bundle extras = data.getExtras();
mBitmap = extras.getParcelable("data");
if (mBitmap != null) {
setPicToView(mBitmap);// 保存在SD卡中
mPersonalDataModification_imageView_Avatar.setImageBitmap(mBitmap);// 用ImageButton显示出来
}
}
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/*
调用系统的裁剪功能,进入裁剪页面
*/
public void cropPhoto(Uri uri){
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri,"image/*");
intent.putExtra("crop","ture");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 250);
intent.putExtra("outputY", 250);
intent.putExtra("return-data", true);
Log.e(TAG,"头像裁剪");
startActivityForResult(intent, ENTER_CROP_PHOTO);
}
/*
显示默认头像或者历史设置的头像
*/
public void getOldAvatar(){
mPersonalDataModification_imageView_Avatar = (ImageView)findViewById(R.id.PersonalDataModification_imageView_Avatar);
//从文件存储里得到图片
Bitmap bt = BitmapFactory.decodeFile(mAvatarPath+mAvatarName);
//判断不是空头像
if (bt != null){
Drawable drawable = new BitmapDrawable(getResources(),bt);
//重新设置头像图片 注意这里使用的是setImageDrawable,不是setImageResource
mPersonalDataModification_imageView_Avatar.setImageDrawable(drawable);
Log.e(TAG,"使用历史头像");
}else {
//如果没有旧的头像就使用系统默认的
mPersonalDataModification_imageView_Avatar.setImageResource(R.drawable.ic_woman_default);
Log.e(TAG,"使用默认头像");
}
}
/*
保存到sd卡是为了下一次进入apk的时候直接读取图片,
*/
private void setPicToView(Bitmap mBitmap) {
String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用
return;
} try {
File dir = new File(mAvatarPath);
dir.mkdirs();// 创建文件夹
File file = new File(mAvatarPath, mAvatarName);
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream b = new FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把图片数据写入图片b
b.flush(); //刷新
b.close(); //关闭
}catch(IOException e){
e.printStackTrace();
}
/*
FileOutputStream b = null;
File file = new File(mAvatarPath);
file.mkdirs();// 创建文件夹
String fileName = mAvatarPath + mAvatarName;// 图片名字
try {
b = new FileOutputStream(fileName);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把图片数据写入图片b
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
b.flush(); //刷新
b.close(); //关闭
} catch (IOException e) {
e.printStackTrace();
}
}
*/
}
}

android 开发 实现一个进入相机拍照后裁剪图片或者进入相册选中裁剪图片的功能的更多相关文章

  1. Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式

    Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式 Fragment FragmentManager frag ...

  2. 2016 校招, Android 开发,一个本科应届的坎坷求职之路(转)

    转载出处:http://www.nowcoder.com/discuss/3244?type=2&order=0&pos=1&page=1 和大多数的面经不同,我不是大牛,手头 ...

  3. android 开发 实现一个app的引导查看页面(使用ViewPager组件)

    我们安装完app后第一次打开app,通常都会有一个翻页图片形式的app引导简介说明.下面我们来实现这个功能.ViewPager这个组件与ListView和RecyclerView在使用上有很高的相似处 ...

  4. Android笔记之调用系统相机拍照

    参考链接: 拍照  |  Android Developers, Android相机拍照方向旋转的解决方案:ExifInterface - 简书 Demo链接:https://pan.baidu.co ...

  5. android 自定义用相机拍照后的照片存储位置

    1.imageUri = Uri.fromFile(new File(Environment .getExternalStorageDirectory()+ File.separator + getP ...

  6. android 相机拍照后选择照片编辑,相片编辑界面直线形状会显示锯齿状

    因为 decode 出来的图片太小,小于屏幕.所以,显示的时候 会把图片略微放大,导致直线形状会显示锯齿状.   能够改动getScreenImageSize 方法中的size 的大小,比方能够把13 ...

  7. android开发 无预览定时拍照

    demo实现功能: 打开主页面自动启动定时拍照,10s拍一次. 注意事项,初始化摄像头之后不能立即拍照,否则无效,必须等待几秒后才能拍.这里用的是Handler进行延时处理拍照消息的. package ...

  8. android 开发 实现一个自定义布局的AlertDialog对话框

    对话框有很多实现方法,最常见的是在一个点击事件中代码直接写出对话框.如下: package com.example.lenovo.mydemo2; import android.content.Dia ...

  9. 记录 android 开发的一个 "面试" 问题

    前序: 3天前,有幸得到师兄赏识,和他一起去帮一间珠海的本地的IT公司担任面试官,虽说如此,我自己本身就还没毕业,充其量是去见识下世面罢了.当天共面试了13人,这只是上午,下午我闪了.在笔试的部分,我 ...

随机推荐

  1. sbt第一次运行下载jar包很慢解决办法

    一.补充sbt配置文件,添加下载路径 文件结构如下:修改了sbtconfig.txt,repo.properties. sbtconfig.txt配置内容为: # Set the java args  ...

  2. Git-git rebase详解

    git合并代码方式主要有两种方式,分别为:1.merge处理,这是大家比较能理解的方式.2.rebase处理,中文此处翻译为衍合过程. git rebase操作讲解例子: cd /usr/local/ ...

  3. 一次修改mysql字段类型引发的技术探究

    说来,mysql数据库是我们项目中用的比较多的库,ORM工具喜欢采用细粒度的MyBatis.这里面就这么引出了两者之间的故事! 首先,说改字段吧,将一个表中的varchar字段改为enum字段.如下: ...

  4. PowerPoint’s Menu is Too Big

    转自: http://jdav.is/2016/08/31/powerpoints-menu-is-too-big/ It seems that when Microsoft deployed the ...

  5. 胖子哥的大数据之路(10)- 基于Hive构建数据仓库实例

    一.引言 基于Hive+Hadoop模式构建数据仓库,是大数据时代的一个不错的选择,本文以郑商所每日交易行情数据为案例,探讨数据Hive数据导入的操作实例. 二.源数据-每日行情数据 三.建表脚本 C ...

  6. STL中erase()的用法

    erase()是STL提供的容器中比较常用的方法之一,它的功能是删除容器中的某些元素,其中它的函数原型如下: 1.有两个参数,且参数类型都是size_t型: string& erase ( s ...

  7. 《Java并发编程实战》笔记-非阻塞算法

    如果在某种算法中,一个线程的失败或挂起不会导致其他线程也失败和挂起,那么这种算法就被称为非阻塞算法.如果在算法的每个步骤中都存在某个线程能够执行下去,那么这种算法也被称为无锁(Lock-Free)算法 ...

  8. Java-Runoob-高级教程-实例-方法:04. Java 实例 – 斐波那契数列

    ylbtech-Java-Runoob-高级教程-实例-方法:04. Java 实例 – 斐波那契数列 1.返回顶部 1. Java 实例 - 斐波那契数列  Java 实例 斐波那契数列指的是这样一 ...

  9. 对象生命周期中至少被GC一次后存活

    Finalize调用流程:GC时,当对象变成(GC Roots)不可达时,若该对象覆盖(重写)了finalize方法并且未执行过finalze方法,则将其放入F-Queue队列,由一低优先级线程执行该 ...

  10. echarts折现图配置

    js引用和div容器 <div id="container" style="height: 100%"></div> <scrip ...