最近在做一个从图库选择图片或拍照,然后裁剪的功能.本来是没问题的,一直在用
- 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的目录.所以就开始打算用这个图片选择器来选图片了.
这个方法就是
- 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">“image/jpeg”</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.
- 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,需要以下方法来获取文件的路径
- <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">“:”</span>);
- <span class="keyword">final</span> String type = split[<span class="number"></span>];
-
- <span class="keyword">if</span> (<span class="string">“primary”</span>.equalsIgnoreCase(type)) {
- <span class="keyword">return</span> Environment.getExternalStorageDirectory() + <span class="string">“/”</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">“content://downloads/public_downloads”</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">“:”</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">“image”</span>.equals(type)) {
- contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
- } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">“video”</span>.equals(type)) {
- contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
- } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">“audio”</span>.equals(type)) {
- contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
- }
-
- <span class="keyword">final</span> String selection = <span class="string">“_id=?”</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">“content”</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">“file”</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">“_data”</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">“com.android.externalstorage.documents”</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">“com.android.providers.downloads.documents”</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">“com.android.providers.media.documents”</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">“com.google.android.apps.photos.content”</span>.equals(uri.getAuthority());
- }
这样,就可以在4.4上用漂亮的图片选择器,选到我们想要的文件,又不会出问题了.
昨天发现了个bug,如果在4.4上面不用”图片”来选,用”图库”来选,就会无法读取到图片路径,所以只需要加个判断,如果是用旧方式来选,就用旧方式来读,就是如果
DocumentsContract.isDocumentUri(context, uri) 返回false的话,就用旧的方式
- <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">“com.sec.android.gallery3d”</span>)){
- Log.e(TAG, <span class="string">“It’s auto backup pic path:”</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:
- <span class="tag"><?</span><span class="tag-name">xml</span> <span class="attribute">version</span>=<span class="attribute-value">“1.0”</span> <span class="attribute">encoding</span>=<span class="attribute-value">“utf-8”</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">“http://schemas.android.com/apk/res/android”</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“wrap_content”</span>
- <span class="attribute">android:gravity</span>=<span class="attribute-value">“center_horizontal”</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">“@+id/dialog_layout”</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“wrap_content”</span>
- <span class="attribute">android:layout_alignParentBottom</span>=<span class="attribute-value">“true”</span>
- <span class="attribute">android:layout_marginLeft</span>=<span class="attribute-value">“10dip”</span>
- <span class="attribute">android:layout_marginRight</span>=<span class="attribute-value">“10dip”</span>
- <span class="attribute">android:gravity</span>=<span class="attribute-value">“center_horizontal”</span>
- <span class="attribute">android:orientation</span>=<span class="attribute-value">“vertical”</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">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“wrap_content”</span>
- <span class="attribute">android:background</span>=<span class="attribute-value">“@drawable/select_photo_up_bg”</span>
- <span class="attribute">android:orientation</span>=<span class="attribute-value">“vertical”</span>
- <span class="attribute">android:paddingBottom</span>=<span class="attribute-value">“5dp”</span>
- <span class="attribute">android:paddingTop</span>=<span class="attribute-value">“5dp”</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">“@+id/btn_take_photo”</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“35dp”</span>
- <span class="attribute">android:background</span>=<span class="attribute-value">“@drawable/select_photo_bg”</span>
- <span class="attribute">android:text</span>=<span class="attribute-value">“拍照选取”</span>
- <span class="attribute">android:textStyle</span>=<span class="attribute-value">“bold”</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">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“0.5px”</span>
- <span class="attribute">android:background</span>=<span class="attribute-value">“#828282”</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">“@+id/btn_pick_photo”</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“35dp”</span>
- <span class="attribute">android:layout_marginTop</span>=<span class="attribute-value">“0dip”</span>
- <span class="attribute">android:background</span>=<span class="attribute-value">“@drawable/select_photo_bg”</span>
- <span class="attribute">android:text</span>=<span class="attribute-value">“相册选取”</span>
- <span class="attribute">android:textStyle</span>=<span class="attribute-value">“bold”</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">“@+id/btn_cancel”</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“35dp”</span>
- <span class="attribute">android:layout_marginTop</span>=<span class="attribute-value">“20dip”</span>
- <span class="attribute">android:background</span>=<span class="attribute-value">“@drawable/select_photo_bg”</span>
- <span class="attribute">android:paddingBottom</span>=<span class="attribute-value">“5dp”</span>
- <span class="attribute">android:paddingTop</span>=<span class="attribute-value">“5dp”</span>
- <span class="attribute">android:text</span>=<span class="attribute-value">“取消”</span>
- <span class="attribute">android:textColor</span>=<span class="attribute-value">“#ffff0000”</span>
- <span class="attribute">android:textStyle</span>=<span class="attribute-value">“bold”</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:
- <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">“photo_path”</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">// “android.media.action.IMAGE_CAPTURE”</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">“内存卡不存在”</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">“image/*”</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">“选择图片文件出错”</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">“选择图片文件出错”</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">“.png”</span>) || picPath.endsWith(<span class="string">“.PNG”</span>)
- || picPath.endsWith(<span class="string">“.jpg”</span>) || picPath.endsWith(<span class="string">“.JPG”</span>))) {
- lastIntent.putExtra(KEY_PHOTO_PATH, picPath);
- setResult(Activity.RESULT_OK, lastIntent);
- finish();
- } <span class="keyword">else</span> {
- Toast.makeText(getApplicationContext(), <span class="string">“选择图片文件不正确”</span>,
- Toast.LENGTH_SHORT).show();
- }
- }
-
- }
因为这Activity是要设置成Dialog模式的,所以需要在清单文件中设置一下style,/res/values/styles.xml里添加如下:
- <span class="tag"><</span><span class="tag-name">style</span> <span class="attribute">name</span>=<span class="attribute-value">“AnimBottom”</span> <span class="attribute">parent</span>=<span class="attribute-value">“@android:style/Animation”</span><span class="tag">></span>
- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">“android:windowEnterAnimation”</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">“android:windowExitAnimation”</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">“DialogStyleBottom”</span> <span class="attribute">parent</span>=<span class="attribute-value">“android:Theme.Dialog”</span><span class="tag">></span>
- <span class="tag"><</span><span class="tag-name">item</span> <span class="attribute">name</span>=<span class="attribute-value">“android:windowAnimationStyle”</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">“android:windowFrame”</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">“android:windowIsFloating”</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">“android:windowIsTranslucent”</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">“android:windowNoTitle”</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">“android:windowBackground”</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">“android:backgroundDimEnabled”</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:
- <span class="tag"><</span><span class="tag-name">activity</span>
- <span class="attribute">android:name</span>=<span class="attribute-value">“com.example.croppictrue.SelectPhotoActivity”</span>
- <span class="attribute">android:screenOrientation</span>=<span class="attribute-value">“portrait”</span>
- <span class="attribute">android:theme</span>=<span class="attribute-value">“@style/DialogStyleBottom”</span> <span class="tag">></span>
- <span class="tag"></</span><span class="tag-name">activity</span><span class="tag">></span>
添加权限:
- <span class="tag"><</span><span class="tag-name">uses-permission</span> <span class="attribute">android:name</span>=<span class="attribute-value">“android.permission.WRITE_EXTERNAL_STORAGE”</span> <span class="tag">/></span>
运行效果如下:
2.通过拍照或者图册获取图片(需要剪裁)
上面第一种方式获取图片是没有经过剪裁的,但是大多项目需求是需要剪裁图片后再使用,例如修改用户头像等等功能。那么,下面,就奉上剪裁图片的代码吧:
- <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">“选择本地图片”</span>, <span class="string">“拍照”</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">“image.jpg”</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">“设置头像”</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">“image/*”</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">“取消”</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">“未找到存储卡,无法存储照片!”</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">“com.android.camera.action.CROP”</span>);
- intent.setDataAndType(uri, <span class="string">“image/*”</span>);
- <span class="comment">// 设置裁剪</span>
- intent.putExtra(<span class="string">“crop”</span>, <span class="string">“true”</span>);
- <span class="comment">// aspectX aspectY 是宽高的比例</span>
- intent.putExtra(<span class="string">“aspectX”</span>, <span class="number">1</span>);
- intent.putExtra(<span class="string">“aspectY”</span>, <span class="number">1</span>);
- <span class="comment">// outputX outputY 是裁剪图片宽高</span>
- intent.putExtra(<span class="string">“outputX”</span>, <span class="number">340</span>);
- intent.putExtra(<span class="string">“outputY”</span>, <span class="number">340</span>);
- intent.putExtra(<span class="string">“return-data”</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">“data”</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的源码,运行在手机上试试看效果如何,如若疏漏之后,欢迎大家批评指正!
💬 评论