最近在做一个从图库选择图片或拍照,然后裁剪的功能.本来是没问题的,一直在用

**[java]** [view plain](http://blog.csdn.net/tempersitu/article/details/20557383#)[copy](http://blog.csdn.net/tempersitu/article/details/20557383#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/219069)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/219069/fork)
- Intent intent=<span class="keyword">new</span> Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

的方式来做,是调用系统图库来做,但是发现如果有图片是同步到google相册的话,图库里面能看到一个auto backup的目录,点进去选图片的话是无法获取到图片的路径的.因为那些图片根本就不存在于手机上.然后看到无论是百度贴吧,Instagram,或者还有些会选取图片做修改的app,都是用一个很漂亮的图片选择器(4.4以上,4.3的还是用系统旧的图库).

而这个图片选择器可以屏蔽掉那个auto backup的目录.所以就开始打算用这个图片选择器来选图片了.
这个方法就是

**[java]** [view plain](http://blog.csdn.net/tempersitu/article/details/20557383#)[copy](http://blog.csdn.net/tempersitu/article/details/20557383#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/219069)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/219069/fork)
- Intent intent=<span class="keyword">new</span> Intent(Intent.ACTION_GET_CONTENT);<span class="comment">//ACTION_OPEN_DOCUMENT</span>

- intent.addCategory(Intent.CATEGORY_OPENABLE);

- intent.setType(<span class="string">&#8220;image/jpeg&#8221;</span>);

- <span class="keyword">if</span>(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT){

- startActivityForResult(intent, SELECT_PIC_KITKAT);

- }<span class="keyword">else</span>{

- startActivityForResult(intent, SELECT_PIC);

- }

 

为什么要分开不同版本呢?其实在4.3或以下可以直接用ACTION_GET_CONTENT的,在4.4或以上,官方建议用ACTION_OPEN_DOCUMENT,但其实都不算太大区别,区别是他们返回的Uri,那个才叫大区别.这就是困扰了我一整天的问题所在了.

4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了.主要是4.4,如果使用上面pick的原生方法来选图,返回的uri还是正常的,但如果用ACTION_GET_CONTENT的方法,返回的uri跟4.3是完全不一样的,4.3返回的是带文件路径的,而4.4返回的却是content://com.android.providers.media.documents/document/image:3951这样的,没有路径,只有图片编号的uri.这就导致接下来无法根据图片路径来裁剪的步骤了.

还好找了很多方法,包括加权限啊什么的,中间还试过用一些方法,自己的app没崩溃,倒是让系统图库崩溃了,引发了java.lang.SecurityException.

**[java]** [view plain](http://blog.csdn.net/tempersitu/article/details/20557383#)[copy](http://blog.csdn.net/tempersitu/article/details/20557383#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/219069)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/219069/fork)
- Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{437b5d88 <span class="number">9494</span>:com.google.android.gallery3d/u0a20} (pid=<span class="number">9494</span>, uid=<span class="number">10020</span>) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS

看来4.4的系统还是有些bug.重点来了,4.4得到的uri,需要以下方法来获取文件的路径

**[java]** [view plain](http://blog.csdn.net/tempersitu/article/details/20557383#)[copy](http://blog.csdn.net/tempersitu/article/details/20557383#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/219069)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/219069/fork)
- <span class="keyword">public</span> <span class="keyword">static</span> String getPath(<span class="keyword">final</span> Context context, <span class="keyword">final</span> Uri uri) {

- 
- <span class="keyword">final</span> <span class="keyword">boolean</span> isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

- 
- <span class="comment">// DocumentProvider</span>

- <span class="keyword">if</span> (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {

- <span class="comment">// ExternalStorageProvider</span>

- <span class="keyword">if</span> (isExternalStorageDocument(uri)) {

- <span class="keyword">final</span> String docId = DocumentsContract.getDocumentId(uri);

- <span class="keyword">final</span> String[] split = docId.split(<span class="string">&#8220;:&#8221;</span>);

- <span class="keyword">final</span> String type = split[<span class="number"></span>];

- 
- <span class="keyword">if</span> (<span class="string">&#8220;primary&#8221;</span>.equalsIgnoreCase(type)) {

- <span class="keyword">return</span> Environment.getExternalStorageDirectory() + <span class="string">&#8220;/&#8221;</span> + split[<span class="number">1</span>];

- }

- 
- <span class="comment">// TODO handle non-primary volumes</span>

- }

- <span class="comment">// DownloadsProvider</span>

- <span class="keyword">else</span> <span class="keyword">if</span> (isDownloadsDocument(uri)) {

- 
- <span class="keyword">final</span> String id = DocumentsContract.getDocumentId(uri);

- <span class="keyword">final</span> Uri contentUri = ContentUris.withAppendedId(

- Uri.parse(<span class="string">&#8220;content://downloads/public_downloads&#8221;</span>), Long.valueOf(id));

- 
- <span class="keyword">return</span> getDataColumn(context, contentUri, <span class="keyword">null</span>, <span class="keyword">null</span>);

- }

- <span class="comment">// MediaProvider</span>

- <span class="keyword">else</span> <span class="keyword">if</span> (isMediaDocument(uri)) {

- <span class="keyword">final</span> String docId = DocumentsContract.getDocumentId(uri);

- <span class="keyword">final</span> String[] split = docId.split(<span class="string">&#8220;:&#8221;</span>);

- <span class="keyword">final</span> String type = split[<span class="number"></span>];

- 
- Uri contentUri = <span class="keyword">null</span>;

- <span class="keyword">if</span> (<span class="string">&#8220;image&#8221;</span>.equals(type)) {

- contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

- } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">&#8220;video&#8221;</span>.equals(type)) {

- contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;

- } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">&#8220;audio&#8221;</span>.equals(type)) {

- contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;

- }

- 
- <span class="keyword">final</span> String selection = <span class="string">&#8220;_id=?&#8221;</span>;

- <span class="keyword">final</span> String[] selectionArgs = <span class="keyword">new</span> String[] {

- split[<span class="number">1</span>]

- };

- 
- <span class="keyword">return</span> getDataColumn(context, contentUri, selection, selectionArgs);

- }

- }

- <span class="comment">// MediaStore (and general)</span>

- <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">&#8220;content&#8221;</span>.equalsIgnoreCase(uri.getScheme())) {

- 
- <span class="comment">// Return the remote address</span>

- <span class="keyword">if</span> (isGooglePhotosUri(uri))

- <span class="keyword">return</span> uri.getLastPathSegment();

- 
- <span class="keyword">return</span> getDataColumn(context, uri, <span class="keyword">null</span>, <span class="keyword">null</span>);

- }

- <span class="comment">// File</span>

- <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">&#8220;file&#8221;</span>.equalsIgnoreCase(uri.getScheme())) {

- <span class="keyword">return</span> uri.getPath();

- }

- 
- <span class="keyword">return</span> <span class="keyword">null</span>;

- }

- 
- <span class="comment">/**</span>

- <span class="comment"> * Get the value of the data column for this Uri. This is useful for</span>

- <span class="comment"> * MediaStore Uris, and other file-based ContentProviders.</span>

- <span class="comment"> *</span>

- <span class="comment"> * @param context The context.</span>

- <span class="comment"> * @param uri The Uri to query.</span>

- <span class="comment"> * @param selection (Optional) Filter used in the query.</span>

- <span class="comment"> * @param selectionArgs (Optional) Selection arguments used in the query.</span>

- <span class="comment"> * @return The value of the _data column, which is typically a file path.</span>

- <span class="comment"> */</span>

- <span class="keyword">public</span> <span class="keyword">static</span> String getDataColumn(Context context, Uri uri, String selection,

- String[] selectionArgs) {

- 
- Cursor cursor = <span class="keyword">null</span>;

- <span class="keyword">final</span> String column = <span class="string">&#8220;_data&#8221;</span>;

- <span class="keyword">final</span> String[] projection = {

- column

- };

- 
- <span class="keyword">try</span> {

- cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,

- <span class="keyword">null</span>);

- <span class="keyword">if</span> (cursor != <span class="keyword">null</span> && cursor.moveToFirst()) {

- <span class="keyword">final</span> <span class="keyword">int</span> index = cursor.getColumnIndexOrThrow(column);

- <span class="keyword">return</span> cursor.getString(index);

- }

- } <span class="keyword">finally</span> {

- <span class="keyword">if</span> (cursor != <span class="keyword">null</span>)

- cursor.close();

- }

- <span class="keyword">return</span> <span class="keyword">null</span>;

- }

- 
- 
- <span class="comment">/**</span>

- <span class="comment"> * @param uri The Uri to check.</span>

- <span class="comment"> * @return Whether the Uri authority is ExternalStorageProvider.</span>

- <span class="comment"> */</span>

- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> isExternalStorageDocument(Uri uri) {

- <span class="keyword">return</span> <span class="string">&#8220;com.android.externalstorage.documents&#8221;</span>.equals(uri.getAuthority());

- }

- 
- <span class="comment">/**</span>

- <span class="comment"> * @param uri The Uri to check.</span>

- <span class="comment"> * @return Whether the Uri authority is DownloadsProvider.</span>

- <span class="comment"> */</span>

- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> isDownloadsDocument(Uri uri) {

- <span class="keyword">return</span> <span class="string">&#8220;com.android.providers.downloads.documents&#8221;</span>.equals(uri.getAuthority());

- }

- 
- <span class="comment">/**</span>

- <span class="comment"> * @param uri The Uri to check.</span>

- <span class="comment"> * @return Whether the Uri authority is MediaProvider.</span>

- <span class="comment"> */</span>

- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> isMediaDocument(Uri uri) {

- <span class="keyword">return</span> <span class="string">&#8220;com.android.providers.media.documents&#8221;</span>.equals(uri.getAuthority());

- }

- 
- <span class="comment">/**</span>

- <span class="comment"> * @param uri The Uri to check.</span>

- <span class="comment"> * @return Whether the Uri authority is Google Photos.</span>

- <span class="comment"> */</span>

- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> isGooglePhotosUri(Uri uri) {

- <span class="keyword">return</span> <span class="string">&#8220;com.google.android.apps.photos.content&#8221;</span>.equals(uri.getAuthority());

- }

 

这样,就可以在4.4上用漂亮的图片选择器,选到我们想要的文件,又不会出问题了.

昨天发现了个bug,如果在4.4上面不用”图片”来选,用”图库”来选,就会无法读取到图片路径,所以只需要加个判断,如果是用旧方式来选,就用旧方式来读,就是如果
DocumentsContract.isDocumentUri(context, uri) 返回false的话,就用旧的方式

**[java]** [view plain](http://blog.csdn.net/tempersitu/article/details/20557383#)[copy](http://blog.csdn.net/tempersitu/article/details/20557383#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/219069)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/219069/fork)
- <span class="keyword">public</span> <span class="keyword">static</span> String selectImage(Context context,Intent data){

- Uri selectedImage = data.getData();

- <span class="comment">//      Log.e(TAG, selectedImage.toString());</span>

- <span class="keyword">if</span>(selectedImage!=<span class="keyword">null</span>){

- String uriStr=selectedImage.toString();

- String path=uriStr.substring(<span class="number">10</span>,uriStr.length());

- <span class="keyword">if</span>(path.startsWith(<span class="string">&#8220;com.sec.android.gallery3d&#8221;</span>)){

- Log.e(TAG, <span class="string">&#8220;It&#8217;s auto backup pic path:&#8221;</span>+selectedImage.toString());

- <span class="keyword">return</span> <span class="keyword">null</span>;

- }

- }

- String[] filePathColumn = { MediaStore.Images.Media.DATA };

- Cursor cursor = context.getContentResolver().query(selectedImage,filePathColumn, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>);

- cursor.moveToFirst();

- <span class="keyword">int</span> columnIndex = cursor.getColumnIndex(filePathColumn[<span class="number"></span>]);

- String picturePath = cursor.getString(columnIndex);

- cursor.close();

- <span class="keyword">return</span> picturePath;

- }

这样就OK的了
转自:http://blog.csdn.net/tempersitu/article/details/20557383

 

android拍照图片选取与图片剪裁

   转载:http://blog.csdn.net/allen315410/article/details/39994913

最近从以前的项目中扒下来一个常用的模块,在这里有必要记录一下的,就是android上获取图片以及裁剪图片,怎么样?这个功能是不是很常用啊,你随便打开一个App,只要它有注册功能都会有设置人物头像的功能,尤其在内容型的app中更为常见,那么这些功能是怎么实现的呢?今天,在这里就记录一下好了,防止以后的项目中也会用到,就直接拿来用好了。

1.通过拍照或者图册获取图片(不需要剪裁)

这种获取图片的方式就比较次了,因为不设置图片的剪裁功能,有可能因为图片过大,导致OOM,但是这种方式也是有必要讲一下的,其获取图片的方式有两种,一是调用系统相机实时拍摄一张图片,二十打开设备上已有的图库,在图库中选择一张照片。这两种方式实现方法都是一个道理,无非就是通过Intent调用系统的东西。下面是源码,首先是图片选择方式的Activity,这个Activity被设置成了Dialog模式,需要进行设置一下。

布局文件/res/layout/activity_select_photo.xml:

**[html]** [view plain](http://blog.csdn.net/allen315410/article/details/39994913#)[copy](http://blog.csdn.net/allen315410/article/details/39994913#)[print](http://blog.csdn.net/allen315410/article/details/39994913#)[?](http://blog.csdn.net/allen315410/article/details/39994913#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/482399)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/482399/fork)
- <span class="tag"><?</span><span class="tag-name">xml</span> <span class="attribute">version</span>=<span class="attribute-value">&#8220;1.0&#8221;</span> <span class="attribute">encoding</span>=<span class="attribute-value">&#8220;utf-8&#8221;</span><span class="tag">?></span>

- <span class="tag"><</span><span class="tag-name">RelativeLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span>

- <span class="attribute">android:gravity</span>=<span class="attribute-value">&#8220;center_horizontal&#8221;</span> <span class="tag">></span>

- 
- <span class="tag"><</span><span class="tag-name">LinearLayout</span>

- <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/dialog_layout&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span>

- <span class="attribute">android:layout_alignParentBottom</span>=<span class="attribute-value">&#8220;true&#8221;</span>

- <span class="attribute">android:layout_marginLeft</span>=<span class="attribute-value">&#8220;10dip&#8221;</span>

- <span class="attribute">android:layout_marginRight</span>=<span class="attribute-value">&#8220;10dip&#8221;</span>

- <span class="attribute">android:gravity</span>=<span class="attribute-value">&#8220;center_horizontal&#8221;</span>

- <span class="attribute">android:orientation</span>=<span class="attribute-value">&#8220;vertical&#8221;</span> <span class="tag">></span>

- 
- <span class="tag"><</span><span class="tag-name">LinearLayout</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span>

- <span class="attribute">android:background</span>=<span class="attribute-value">&#8220;@drawable/select_photo_up_bg&#8221;</span>

- <span class="attribute">android:orientation</span>=<span class="attribute-value">&#8220;vertical&#8221;</span>

- <span class="attribute">android:paddingBottom</span>=<span class="attribute-value">&#8220;5dp&#8221;</span>

- <span class="attribute">android:paddingTop</span>=<span class="attribute-value">&#8220;5dp&#8221;</span> <span class="tag">></span>

- 
- <span class="tag"><</span><span class="tag-name">Button</span>

- <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/btn_take_photo&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;35dp&#8221;</span>

- <span class="attribute">android:background</span>=<span class="attribute-value">&#8220;@drawable/select_photo_bg&#8221;</span>

- <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;拍照选取&#8221;</span>

- <span class="attribute">android:textStyle</span>=<span class="attribute-value">&#8220;bold&#8221;</span> <span class="tag">/></span>

- 
- <span class="tag"><</span><span class="tag-name">View</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;0.5px&#8221;</span>

- <span class="attribute">android:background</span>=<span class="attribute-value">&#8220;#828282&#8221;</span> <span class="tag">/></span>

- 
- <span class="tag"><</span><span class="tag-name">Button</span>

- <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/btn_pick_photo&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;35dp&#8221;</span>

- <span class="attribute">android:layout_marginTop</span>=<span class="attribute-value">&#8220;0dip&#8221;</span>

- <span class="attribute">android:background</span>=<span class="attribute-value">&#8220;@drawable/select_photo_bg&#8221;</span>

- <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;相册选取&#8221;</span>

- <span class="attribute">android:textStyle</span>=<span class="attribute-value">&#8220;bold&#8221;</span> <span class="tag">/></span>

- <span class="tag"></</span><span class="tag-name">LinearLayout</span><span class="tag">></span>

- 
- <span class="tag"><</span><span class="tag-name">Button</span>

- <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/btn_cancel&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;35dp&#8221;</span>

- <span class="attribute">android:layout_marginTop</span>=<span class="attribute-value">&#8220;20dip&#8221;</span>

- <span class="attribute">android:background</span>=<span class="attribute-value">&#8220;@drawable/select_photo_bg&#8221;</span>

- <span class="attribute">android:paddingBottom</span>=<span class="attribute-value">&#8220;5dp&#8221;</span>

- <span class="attribute">android:paddingTop</span>=<span class="attribute-value">&#8220;5dp&#8221;</span>

- <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;取消&#8221;</span>

- <span class="attribute">android:textColor</span>=<span class="attribute-value">&#8220;#ffff0000&#8221;</span>

- <span class="attribute">android:textStyle</span>=<span class="attribute-value">&#8220;bold&#8221;</span> <span class="tag">/></span>

- <span class="tag"></</span><span class="tag-name">LinearLayout</span><span class="tag">></span>

- 
- <span class="tag"></</span><span class="tag-name">RelativeLayout</span><span class="tag">></span>

接着是获取图片Activity里的代码SelectPhotoActivity:

**[java]** [view plain](http://blog.csdn.net/allen315410/article/details/39994913#)[copy](http://blog.csdn.net/allen315410/article/details/39994913#)[print](http://blog.csdn.net/allen315410/article/details/39994913#)[?](http://blog.csdn.net/allen315410/article/details/39994913#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/482399)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/482399/fork)
- <span class="keyword">public</span> <span class="keyword">class</span> SelectPhotoActivity <span class="keyword">extends</span> Activity <span class="keyword">implements</span> OnClickListener {

- <span class="comment">/** 使用照相机拍照获取图片 */</span>

- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> SELECT_PIC_BY_TACK_PHOTO = <span class="number">1</span>;

- <span class="comment">/** 使用相册中的图片 */</span>

- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> SELECT_PIC_BY_PICK_PHOTO = <span class="number">2</span>;

- <span class="comment">/** 开启相机 */</span>

- <span class="keyword">private</span> Button btn_take_photo;

- <span class="comment">/** 开启图册 */</span>

- <span class="keyword">private</span> Button btn_pick_photo;

- <span class="comment">/** 取消 */</span>

- <span class="keyword">private</span> Button btn_cancel;

- <span class="comment">/** 获取到的图片路径 */</span>

- <span class="keyword">private</span> String picPath;

- <span class="keyword">private</span> Intent lastIntent;

- <span class="keyword">private</span> Uri photoUri;

- <span class="comment">/** 从Intent获取图片路径的KEY */</span>

- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String KEY_PHOTO_PATH = <span class="string">&#8220;photo_path&#8221;</span>;

- 
- <span class="annotation">@Override</span>

- <span class="keyword">protected</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) {

- <span class="keyword">super</span>.onCreate(savedInstanceState);

- setContentView(R.layout.activity_select_photo);

- btn_take_photo = (Button) findViewById(R.id.btn_take_photo);

- btn_pick_photo = (Button) findViewById(R.id.btn_pick_photo);

- btn_cancel = (Button) findViewById(R.id.btn_cancel);

- 
- lastIntent = getIntent();

- 
- btn_take_photo.setOnClickListener(<span class="keyword">this</span>);

- btn_pick_photo.setOnClickListener(<span class="keyword">this</span>);

- btn_cancel.setOnClickListener(<span class="keyword">this</span>);

- }

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) {

- <span class="keyword">switch</span> (v.getId()) {

- <span class="keyword">case</span> R.id.btn_take_photo : <span class="comment">// 开启相机</span>

- takePhoto();

- <span class="keyword">break</span>;

- <span class="keyword">case</span> R.id.btn_pick_photo : <span class="comment">// 开启图册</span>

- pickPhoto();

- <span class="keyword">break</span>;

- <span class="keyword">case</span> R.id.btn_cancel : <span class="comment">// 取消操作</span>

- <span class="keyword">this</span>.finish();

- <span class="keyword">break</span>;

- <span class="keyword">default</span> :

- <span class="keyword">break</span>;

- }

- }

- 
- <span class="comment">/**</span>

- <span class="comment">     * 拍照获取图片</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">void</span> takePhoto() {

- <span class="comment">// 执行拍照前,应该先判断SD卡是否存在</span>

- String SDState = Environment.getExternalStorageState();

- <span class="keyword">if</span> (SDState.equals(Environment.MEDIA_MOUNTED)) {

- Intent intent = <span class="keyword">new</span> Intent(MediaStore.ACTION_IMAGE_CAPTURE);<span class="comment">// &#8220;android.media.action.IMAGE_CAPTURE&#8221;</span>

- <span class="comment">/***</span>

- <span class="comment">             * 需要说明一下,以下操作使用照相机拍照,拍照后的图片会存放在相册中的 这里使用的这种方式有一个好处就是获取的图片是拍照后的原图</span>

- <span class="comment">             * 如果不实用ContentValues存放照片路径的话,拍照后获取的图片为缩略图不清晰</span>

- <span class="comment">             */</span>

- ContentValues values = <span class="keyword">new</span> ContentValues();

- photoUri = <span class="keyword">this</span>.getContentResolver().insert(

- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

- intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);

- startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);

- } <span class="keyword">else</span> {

- Toast.makeText(getApplicationContext(), <span class="string">&#8220;内存卡不存在&#8221;</span>,

- Toast.LENGTH_SHORT).show();

- }

- }

- 
- <span class="comment">/***</span>

- <span class="comment">     * 从相册中取图片</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">void</span> pickPhoto() {

- Intent intent = <span class="keyword">new</span> Intent();

- intent.setType(<span class="string">&#8220;image/*&#8221;</span>);

- intent.setAction(Intent.ACTION_GET_CONTENT);

- startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);

- }

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">boolean</span> onTouchEvent(MotionEvent event) {

- finish();

- <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(event);

- }

- 
- <span class="annotation">@Override</span>

- <span class="keyword">protected</span> <span class="keyword">void</span> onActivityResult(<span class="keyword">int</span> requestCode, <span class="keyword">int</span> resultCode, Intent data) {

- <span class="keyword">if</span> (resultCode == Activity.RESULT_OK) {

- doPhoto(requestCode, data);

- }

- <span class="keyword">super</span>.onActivityResult(requestCode, resultCode, data);

- }

- 
- /**

- * 选择图片后,获取图片的路径

- *

- * <span class="annotation">@param</span> requestCode

- * <span class="annotation">@param</span> data

- */

- <span class="keyword">private</span> <span class="keyword">void</span> doPhoto(<span class="keyword">int</span> requestCode, Intent data) {

- <span class="keyword">if</span> (requestCode == SELECT_PIC_BY_PICK_PHOTO) {<span class="comment">// 从相册取图片,有些手机有异常情况,请注意</span>

- <span class="keyword">if</span> (data == <span class="keyword">null</span>) {

- Toast.makeText(getApplicationContext(), <span class="string">&#8220;选择图片文件出错&#8221;</span>,

- Toast.LENGTH_SHORT).show();

- <span class="keyword">return</span>;

- }

- photoUri = data.getData();

- <span class="keyword">if</span> (photoUri == <span class="keyword">null</span>) {

- Toast.makeText(getApplicationContext(), <span class="string">&#8220;选择图片文件出错&#8221;</span>,

- Toast.LENGTH_SHORT).show();

- <span class="keyword">return</span>;

- }

- }

- String[] pojo = {MediaStore.Images.Media.DATA};

- Cursor cursor = managedQuery(photoUri, pojo, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>);

- <span class="keyword">if</span> (cursor != <span class="keyword">null</span>) {

- <span class="keyword">int</span> columnIndex = cursor.getColumnIndexOrThrow(pojo[<span class="number"></span>]);

- cursor.moveToFirst();

- picPath = cursor.getString(columnIndex);

- cursor.close();

- }

- <span class="keyword">if</span> (picPath != <span class="keyword">null</span>

- && (picPath.endsWith(<span class="string">&#8220;.png&#8221;</span>) || picPath.endsWith(<span class="string">&#8220;.PNG&#8221;</span>)

- || picPath.endsWith(<span class="string">&#8220;.jpg&#8221;</span>) || picPath.endsWith(<span class="string">&#8220;.JPG&#8221;</span>))) {

- lastIntent.putExtra(KEY_PHOTO_PATH, picPath);

- setResult(Activity.RESULT_OK, lastIntent);

- finish();

- } <span class="keyword">else</span> {

- Toast.makeText(getApplicationContext(), <span class="string">&#8220;选择图片文件不正确&#8221;</span>,

- Toast.LENGTH_SHORT).show();

- }

- }

- 
- }

因为这Activity是要设置成Dialog模式的,所以需要在清单文件中设置一下style,/res/values/styles.xml里添加如下:

**[html]** [view plain](http://blog.csdn.net/allen315410/article/details/39994913#)[copy](http://blog.csdn.net/allen315410/article/details/39994913#)[print](http://blog.csdn.net/allen315410/article/details/39994913#)[?](http://blog.csdn.net/allen315410/article/details/39994913#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/482399)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/482399/fork)
- <span class="tag"><</span><span class="tag-name">style</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;AnimBottom&#8221;</span> <span class="attribute">parent</span>=<span class="attribute-value">&#8220;@android:style/Animation&#8221;</span><span class="tag">></span>

- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:windowEnterAnimation&#8221;</span><span class="tag">></span>@anim/push_bottom_in<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>

- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:windowExitAnimation&#8221;</span><span class="tag">></span>@anim/push_bottom_out<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>

- <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span>

- 
- <span class="tag"><</span><span class="tag-name">style</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;DialogStyleBottom&#8221;</span> <span class="attribute">parent</span>=<span class="attribute-value">&#8220;android:Theme.Dialog&#8221;</span><span class="tag">></span>

- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:windowAnimationStyle&#8221;</span><span class="tag">></span>@style/AnimBottom<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>

- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:windowFrame&#8221;</span><span class="tag">></span>@null<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>


- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:windowIsFloating&#8221;</span><span class="tag">></span>false<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>


- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:windowIsTranslucent&#8221;</span><span class="tag">></span>true<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>


- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:windowNoTitle&#8221;</span><span class="tag">></span>true<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>


- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:windowBackground&#8221;</span><span class="tag">></span>@android:color/transparent<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>


- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">&#8220;android:backgroundDimEnabled&#8221;</span><span class="tag">></span>true<span class="tag"></</span><span class="tag-name">item</span><span class="tag">></span>


- <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span>

在Activity的节点下,设置这个style:

**[html]** [view plain](http://blog.csdn.net/allen315410/article/details/39994913#)[copy](http://blog.csdn.net/allen315410/article/details/39994913#)[print](http://blog.csdn.net/allen315410/article/details/39994913#)[?](http://blog.csdn.net/allen315410/article/details/39994913#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/482399)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/482399/fork)
- <span class="tag"><</span><span class="tag-name">activity</span>

- <span class="attribute">android:name</span>=<span class="attribute-value">&#8220;com.example.croppictrue.SelectPhotoActivity&#8221;</span>

- <span class="attribute">android:screenOrientation</span>=<span class="attribute-value">&#8220;portrait&#8221;</span>

- <span class="attribute">android:theme</span>=<span class="attribute-value">&#8220;@style/DialogStyleBottom&#8221;</span> <span class="tag">></span>

- <span class="tag"></</span><span class="tag-name">activity</span><span class="tag">></span>

添加权限:

**[html]** [view plain](http://blog.csdn.net/allen315410/article/details/39994913#)[copy](http://blog.csdn.net/allen315410/article/details/39994913#)[print](http://blog.csdn.net/allen315410/article/details/39994913#)[?](http://blog.csdn.net/allen315410/article/details/39994913#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/482399)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/482399/fork)
- <span class="tag"><</span><span class="tag-name">uses-permission</span> <span class="attribute">android:name</span>=<span class="attribute-value">&#8220;android.permission.WRITE_EXTERNAL_STORAGE&#8221;</span> <span class="tag">/></span>

运行效果如下:

   

2.通过拍照或者图册获取图片(需要剪裁)

上面第一种方式获取图片是没有经过剪裁的,但是大多项目需求是需要剪裁图片后再使用,例如修改用户头像等等功能。那么,下面,就奉上剪裁图片的代码吧:

**[java]** [view plain](http://blog.csdn.net/allen315410/article/details/39994913#)[copy](http://blog.csdn.net/allen315410/article/details/39994913#)[print](http://blog.csdn.net/allen315410/article/details/39994913#)[?](http://blog.csdn.net/allen315410/article/details/39994913#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/482399)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/482399/fork)
- <span class="keyword">public</span> <span class="keyword">class</span> CropPictureActivity <span class="keyword">extends</span> Activity {

- 
- <span class="comment">/** ImageView对象 */</span>

- <span class="keyword">private</span> ImageView iv_photo;

- <span class="keyword">private</span> String[] items = <span class="keyword">new</span> String[]{<span class="string">&#8220;选择本地图片&#8221;</span>, <span class="string">&#8220;拍照&#8221;</span>};

- <span class="comment">/** 头像名称 */</span>

- <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String IMAGE_FILE_NAME = <span class="string">&#8220;image.jpg&#8221;</span>;

- 
- <span class="comment">/** 请求码 */</span>

- <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> IMAGE_REQUEST_CODE = <span class="number"></span>;

- <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> CAMERA_REQUEST_CODE = <span class="number">1</span>;

- <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> RESULT_REQUEST_CODE = <span class="number">2</span>;

- 
- <span class="annotation">@Override</span>

- <span class="keyword">protected</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) {

- <span class="keyword">super</span>.onCreate(savedInstanceState);

- setContentView(R.layout.activity_crop);

- iv_photo = (ImageView) findViewById(R.id.iv_photo);

- iv_photo.setOnClickListener(<span class="keyword">new</span> OnClickListener() {

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) {

- showDialog();

- }

- });

- }

- 
- <span class="comment">/**</span>

- <span class="comment">     * 显示选择对话框</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">void</span> showDialog() {

- 
- <span class="keyword">new</span> AlertDialog.Builder(<span class="keyword">this</span>)

- .setTitle(<span class="string">&#8220;设置头像&#8221;</span>)

- .setItems(items, <span class="keyword">new</span> DialogInterface.OnClickListener() {

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onClick(DialogInterface dialog, <span class="keyword">int</span> which) {

- <span class="keyword">switch</span> (which) {

- <span class="keyword">case</span> <span class="number"></span> :

- Intent intentFromGallery = <span class="keyword">new</span> Intent();

- intentFromGallery.setType(<span class="string">&#8220;image/*&#8221;</span>); <span class="comment">// 设置文件类型</span>

- intentFromGallery

- .setAction(Intent.ACTION_GET_CONTENT);

- startActivityForResult(intentFromGallery,

- IMAGE_REQUEST_CODE);

- <span class="keyword">break</span>;

- <span class="keyword">case</span> <span class="number">1</span> :

- Intent intentFromCapture = <span class="keyword">new</span> Intent(

- MediaStore.ACTION_IMAGE_CAPTURE);

- <span class="comment">// 判断存储卡是否可以用,可用进行存储</span>

- String state = Environment

- .getExternalStorageState();

- <span class="keyword">if</span> (state.equals(Environment.MEDIA_MOUNTED)) {

- File path = Environment

- .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);

- File file = <span class="keyword">new</span> File(path, IMAGE_FILE_NAME);

- intentFromCapture.putExtra(

- MediaStore.EXTRA_OUTPUT,

- Uri.fromFile(file));

- }

- 
- startActivityForResult(intentFromCapture,

- CAMERA_REQUEST_CODE);

- <span class="keyword">break</span>;

- }

- }

- })

- .setNegativeButton(<span class="string">&#8220;取消&#8221;</span>, <span class="keyword">new</span> DialogInterface.OnClickListener() {

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onClick(DialogInterface dialog, <span class="keyword">int</span> which) {

- dialog.dismiss();

- }

- }).show();

- 
- }

- 
- <span class="annotation">@Override</span>

- <span class="keyword">protected</span> <span class="keyword">void</span> onActivityResult(<span class="keyword">int</span> requestCode, <span class="keyword">int</span> resultCode, Intent data) {

- <span class="comment">// 结果码不等于取消时候</span>

- <span class="keyword">if</span> (resultCode != RESULT_CANCELED) {

- <span class="keyword">switch</span> (requestCode) {

- <span class="keyword">case</span> IMAGE_REQUEST_CODE :

- startPhotoZoom(data.getData());

- <span class="keyword">break</span>;

- <span class="keyword">case</span> CAMERA_REQUEST_CODE :

- <span class="comment">// 判断存储卡是否可以用,可用进行存储</span>

- String state = Environment.getExternalStorageState();

- <span class="keyword">if</span> (state.equals(Environment.MEDIA_MOUNTED)) {

- File path = Environment

- .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);

- File tempFile = <span class="keyword">new</span> File(path, IMAGE_FILE_NAME);

- startPhotoZoom(Uri.fromFile(tempFile));

- } <span class="keyword">else</span> {

- Toast.makeText(getApplicationContext(),

- <span class="string">&#8220;未找到存储卡,无法存储照片!&#8221;</span>, Toast.LENGTH_SHORT).show();

- }

- <span class="keyword">break</span>;

- <span class="keyword">case</span> RESULT_REQUEST_CODE : <span class="comment">// 图片缩放完成后</span>

- <span class="keyword">if</span> (data != <span class="keyword">null</span>) {

- getImageToView(data);

- }

- <span class="keyword">break</span>;

- }

- }

- <span class="keyword">super</span>.onActivityResult(requestCode, resultCode, data);

- }

- 
- /**

- * 裁剪图片方法实现

- *

- * <span class="annotation">@param</span> uri

- */

- <span class="keyword">public</span> <span class="keyword">void</span> startPhotoZoom(Uri uri) {

- Intent intent = <span class="keyword">new</span> Intent(<span class="string">&#8220;com.android.camera.action.CROP&#8221;</span>);

- intent.setDataAndType(uri, <span class="string">&#8220;image/*&#8221;</span>);

- <span class="comment">// 设置裁剪</span>

- intent.putExtra(<span class="string">&#8220;crop&#8221;</span>, <span class="string">&#8220;true&#8221;</span>);

- <span class="comment">// aspectX aspectY 是宽高的比例</span>

- intent.putExtra(<span class="string">&#8220;aspectX&#8221;</span>, <span class="number">1</span>);

- intent.putExtra(<span class="string">&#8220;aspectY&#8221;</span>, <span class="number">1</span>);

- <span class="comment">// outputX outputY 是裁剪图片宽高</span>

- intent.putExtra(<span class="string">&#8220;outputX&#8221;</span>, <span class="number">340</span>);

- intent.putExtra(<span class="string">&#8220;outputY&#8221;</span>, <span class="number">340</span>);

- intent.putExtra(<span class="string">&#8220;return-data&#8221;</span>, <span class="keyword">true</span>);

- startActivityForResult(intent, RESULT_REQUEST_CODE);

- }

- 
- /**

- * 保存裁剪之后的图片数据

- *

- * <span class="annotation">@param</span> picdata

- */

- <span class="keyword">private</span> <span class="keyword">void</span> getImageToView(Intent data) {

- Bundle extras = data.getExtras();

- <span class="keyword">if</span> (extras != <span class="keyword">null</span>) {

- Bitmap photo = extras.getParcelable(<span class="string">&#8220;data&#8221;</span>);

- Drawable drawable = <span class="keyword">new</span> BitmapDrawable(<span class="keyword">this</span>.getResources(), photo);

- iv_photo.setImageDrawable(drawable);

- }

- }

- }

效果图:

     

在这个Activity里为了简便处理,我没有在选择图片时候start一个Dialog风格的Activity了,就直接一个普通的对话框提示用户选择,效果也许。其实实现的原理都比较简单,实现图片的剪裁就是发一个Intent请求,调用设备上所有具有剪裁图片功能的app去剪裁图片,我的设备上除了android系统自带的图库以外,还装有“快图浏览”这个app,这个app也自带一个图片剪裁的功能,所有当选择好图片后,会出现一个选择提示,用户可以根据提示选择到底使用哪个app提供的剪裁功能区剪裁图片。
以上代码均在模拟器上测试过,由于模拟器对相机支持的不好,所以就没有演示打开相机拍摄图片了,有兴趣的朋友可以先请下载这个Demo的源码,运行在手机上试试看效果如何,如若疏漏之后,欢迎大家批评指正!

源码请在这里下载