android拍照并剪辑

前几天接到了这个任务,看起来似乎并不复杂,但实际情况却让我大为头疼,先来简单介绍一下整体流程:

最基础的一步,莫过于调用相机拍摄了,

 

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, null);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));

startActivityForResult(cIntent, PIC_REQUEST_CODE_SELECT_CAMERA);

当然也可以不加输出,直接调用,那么会返回一个压缩过的图片

 

在onActivityResult中填写相应处理,添加调用gallery剪辑图片 和 剪辑后处理的两个分支:

 

调用galler:

        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(Uri.fromFile(mCurrentPhotoFile), "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", 80);
        intent.putExtra("outputY", 80);
        intent.putExtra("return-data", true);

        startActivityForResult(intent, PIC_REQUEST_CODE_WITH_DATA);

调用后处理:

略。

 

看似很简单,模拟器运行也没问题,但真机运行起来总是出错,究其原因,是sdk版本问题

(总是说android 版本向下兼容,今天就碰到问题了)

模拟器用的是2.0,而手机是2.1,查了资料后发现

 

“2.1系统对 gallery 这个调用进行了修改,uri不让传file:///了,只能传图库中的图片,
 比如此类uri:content://media/external/images/media/3
所以需要把FIle的Uri 转化成图库的Uri” (这段是看别人帖子知道的,记不清在哪了)

 

找到问题就改吧,把Uri.fromFile(mCurrentPhotoFile)改掉,用ContentResolver查一下媒体库总可以了吧

Cursor cursor = cr.query(imgUri, null,MediaStore.Images.Media.DISPLAY_NAME + "='"+mCurrentPhotoFile.getName()+"'", null, null);

if(cursor!=null&& cursor.getCount()>0){
                cursor.moveToLast();
                id=cursor.getLong(0);
                Uri uri = ContentUris.withAppendedId(imgUri,id);//Uri.fromFile(mCurrentPhotoFile);
            }

 

这下总可以了吧,结果还是让我很头疼,

始终查不到新拍的相片,文件已经存了啊,一开始还以为查询写错了

不停的找啊找,改呀改,没有任何进展

纠结了半天后才发现,压根就不是查询的问题,是因为有些手机,

拍照后,相片并不能即时进入媒体库,包括视频和音频

需要刷新才可以,折磨了我两天的问题终于找到根了

那就在查询之前刷新吧

刷新有两种方法:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, dirUri));  //刷新sd卡
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,fileUri)); //刷新单个文件

刷新后再查询,还是有问题,刷新也是要时间的,需要有个异步处理

对于刷新sd卡来说, 我们可以定义一个接收器来处理,单个文件的接收却始终找不到合适的方法

只能写个线程,来扫描数据库,有新增的图片了,再调用gallery

到此,功能是实现了,对于我这个初学者来说,

真是煞费苦心啊,不过也是收获不少,代码也一并奉上,希望与有相同经历的同志共勉:

 

 

package lv.test;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class Main extends Activity implements OnClickListener {
   
    String TAG = "lvtest";
    private Button btn;
    private ImageView img;
   
    private Button btn2;
    private ImageView img2;
    private ImageView img3;
    private static final File PHOTO_DIR = new File(Environment.getExternalStorageDirectory()+ "/DCIM/Camera");
    private File mCurrentPhotoFile;//
    private static MediaActionReceiver actionReceiver;
    private static final int SCAN_MEDIA_START = 1;
    private static final int SCAN_MEDIA_FINISH = 2;
    private static final int SCAN_MEDIA_FILE = 3;
    private static final int SCAN_MEDIA_FILE_FINISH_INT = 4;
    private static final int SCAN_MEDIA_FILE_FAIL_INT = 5;
    ProgressDialog delLoadingDialog = null;
    HeadImageGetter imageGet;
    private String tag = "lvtest";
    private static final String SCAN_MEDIA_FILE_FINISH = "ACTION_MEDIA_SCANNER_SCAN_FILE_FINISH";
    private static final String SCAN_MEDIA_FILE_FAIL = "ACTION_MEDIA_SCANNER_SCAN_FILE_FAIL";

    private static final int PIC_REQUEST_CODE_WITH_DATA = 1;    // 标识获取图片数据
    private static final int PIC_REQUEST_CODE_SELECT_CAMERA = 2;    // 标识请求照相功能的activity
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button)this.findViewById(R.id.Button01);
        btn.setOnClickListener(this);
        img = (ImageView)this.findViewById(R.id.ImageView01);
        img.setImageResource(R.drawable.i_happy);
       
       
        btn2 = (Button)this.findViewById(R.id.Button02);
        btn2.setOnClickListener(this);
        img2 = (ImageView)this.findViewById(R.id.ImageView02);
        img2.setImageResource(R.drawable.i_cry);
       
        img3 = (ImageView)this.findViewById(R.id.ImageView03);
        img3.setImageResource(R.drawable.i_cry);
       
        actionReceiver = new MediaActionReceiver();

    }

    /* (non-Javadoc)
     * @see android.app.Activity#onDestroy()
     */
    @Override
    protected void onDestroy() {
        try {
            unregisterReceiver(actionReceiver);
        } catch (Exception e) {
            Log.e(TAG, "actionReceiver not registed");
        }
        super.onDestroy();
    }
   
    /**
     * 定义receiver接收其他线程的广播
     *
     */
    public class MediaActionReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Intent.ACTION_MEDIA_SCANNER_STARTED.equals(action)) {
                mHandler.sendEmptyMessage(SCAN_MEDIA_START);
            }
            if (Intent.ACTION_MEDIA_SCANNER_FINISHED.equals(action)) {
                mHandler.sendEmptyMessage(SCAN_MEDIA_FINISH);
            }
            if (Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)) {
                mHandler.sendEmptyMessage(SCAN_MEDIA_FILE);
            }
        }
    }
   
    public Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
                            switch (msg.what) {
                            case SCAN_MEDIA_START:
                                Log.i(TAG, "sccan media started");
                                delLoadingDialog = onCreateDialogByResId(R.string.loading);
                                delLoadingDialog.show();
                                break;
                            case SCAN_MEDIA_FINISH:
                                Log.i(TAG, "sccan media finish");
                                galleryPhoto();
                               
                                break;
                               
                            case SCAN_MEDIA_FILE:
                                Log.i(TAG, "sccan file");
                                delLoadingDialog = onCreateDialogByResId(R.string.loading);
                                delLoadingDialog.show();
                                ScanMediaThread sthread = new ScanMediaThread(Main.this,40,300);
                                sthread.run();
                                break;
                               
                            case SCAN_MEDIA_FILE_FINISH_INT:
                                Log.i(TAG, "sccan file finish");
                                galleryPhoto();
                                break;
                               
                            case SCAN_MEDIA_FILE_FAIL_INT:
                                Log.i(TAG, "sccan file fail");
                                if (delLoadingDialog!=null && delLoadingDialog.isShowing()) {
                                    delLoadingDialog.dismiss();                       
                                }
                               
                                try {
                                    unregisterReceiver(actionReceiver);
                                } catch (Exception e) {
                                    Log.e(TAG, "actionReceiver not registed");
                                }
                               
                                Toast.makeText(Main.this, "no take photo",
                                        Toast.LENGTH_LONG).show();
                                break;

                           
        }
    }
    };
   
    private void galleryPhoto(){
        try {
            long id = 0;
            Uri imgUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;                       
            ContentResolver cr = Main.this.getContentResolver();

            Cursor cursor = cr.query(imgUri, null,MediaStore.Images.Media.DISPLAY_NAME + "='"+mCurrentPhotoFile.getName()+"'", null, null);
           
            if(cursor!=null&& cursor.getCount()>0){
                cursor.moveToLast();
                id=cursor.getLong(0);

                /*
                 * update by lvxuejun on 20110322
                 * 2.1系统对 gallery 这个调用进行了修改,uri不让传file:///了,只能传图库中的图片,
                 * 比如此类uri:content://media/external/images/media/3
                 * 所以需要把FIle的Uri 转化成图库的Uri
                */
                Uri uri = ContentUris.withAppendedId(imgUri,id);//Uri.fromFile(mCurrentPhotoFile);

                // 启动gallery去剪辑这个照片
                final Intent intent = getCropImageIntent(uri);
                if (intent!=null) {
                    startActivityForResult(intent, PIC_REQUEST_CODE_WITH_DATA);
                }
               
            }

            if (delLoadingDialog!=null && delLoadingDialog.isShowing()) {
                delLoadingDialog.dismiss();                       
            }
           
            try {
                unregisterReceiver(actionReceiver);
            } catch (Exception e) {
                Log.e(TAG, "actionReceiver not registed");
            }
        } catch (Exception ee) {
            // TODO Auto-generated catch block
            Log.e(TAG, "",ee);
           
        }
    }
   
   
    /**
     * 根据资源ID获得ProgressDialog对象
     *
     * @param resId
     * @return
     */
    protected ProgressDialog onCreateDialogByResId(int resId) {
        ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage(getResources().getText(resId));
        dialog.setIndeterminate(true);
        dialog.setCancelable(true);
        return dialog;
    }
   
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.Button01:
            try {
                PHOTO_DIR.mkdirs();// 创建照片的存储目录
                mCurrentPhotoFile = new File(PHOTO_DIR, getPhotoFileName());// 给新照的照片文件命名
           
                final Intent cIntent = getTakePickIntent(mCurrentPhotoFile);
                //final Intent cIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, null);
                startActivityForResult(cIntent, PIC_REQUEST_CODE_SELECT_CAMERA);
               
            } catch (ActivityNotFoundException e) {
                Toast.makeText(this, "",
                        Toast.LENGTH_LONG).show();
            }
            break;
       
        default:
            break;
        }
        // TODO Auto-generated method stub
       
    }
   
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK)
        {
            switch (requestCode) {
               
                // 调用Gallery返回的
                case PIC_REQUEST_CODE_WITH_DATA: {
                    final Bitmap photo = data.getParcelableExtra("data");
                    //缓存用户选择的图片

                    img.setImageBitmap(photo);

                    break;
                }
                // 照相机程序返回的,再次调用图片剪辑程序去修剪图片
                case PIC_REQUEST_CODE_SELECT_CAMERA: {
                    try {
                       
                         Uri fileUri = Uri.fromFile(mCurrentPhotoFile);
                   
                         Uri dirUri = Uri.parse("file://" + Environment.getExternalStorageDirectory()+ "/DCIM/Camera");

                         try {
                            IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
                             intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
                             intentFilter.addDataScheme("file");      
                             intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                             registerReceiver(actionReceiver,intentFilter);
                        } catch (RuntimeException e) {
                           
                        }
                       
                         //sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, dirUri)); 
                         sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, fileUri));

                    } catch (Exception e) {
                        Log.e(TAG, "Cannot crop image:", e);
                    }
                    break;
                }
            }
        }
    }
   
   
    public static Intent getTakePickIntent(File f) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, null);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
           
        return intent;
    }
   
    /**
     * Constructs an intent for image cropping. 调用图片剪辑程序
     */
    public static Intent getCropImageIntent(Uri photoUri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setClassName("com.android.camera", "com.android.camera.CropImage");
        //intent.setDataAndType(photoUri, "image/*");
        intent.setData(photoUri);
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", 80);
        intent.putExtra("outputY", 80);
        intent.putExtra("return-data", true);
        return intent;
    }
   
   
    // 用当前时间给取得的图片命名
    private String getPhotoFileName() {
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat dateFormat = new SimpleDateFormat(
                "'IMG'_yyyyMMdd_HHmmss");
        return dateFormat.format(date) + ".jpg";
    }

    public class ScanMediaThread extends Thread{
        private int scanCount=5;
        private int interval=50;
        private Context cx = null;
       
        public ScanMediaThread(Context context,int count,int i){
            scanCount = count;
            interval =  i;
            cx = context;
            this.setName(System.currentTimeMillis() + "_ScanMediaThread");
        }
       
        @Override
        public void run() {
            Log.i(TAG,"scan thread start");
            if (this.cx == null)
                return;
            try {
                int j = 0;
                long id = 0;
                Uri imgUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;                       
                ContentResolver cr = Main.this.getContentResolver();

                Cursor cursor;
                for (j = 0; j < this.scanCount; j++) {
                    Thread.sleep(this.interval);
                    cursor = cr.query(imgUri, null,MediaStore.Images.Media.DISPLAY_NAME + "='"+mCurrentPhotoFile.getName()+"'", null, null);
                    Log.i(TAG,"scan thread "+ j);
                    if(cursor!=null&& cursor.getCount()>0){
                        Log.i(TAG,"send finish " + SCAN_MEDIA_FILE_FINISH);
                        //cx.sendBroadcast(new Intent(SCAN_MEDIA_FILE_FINISH));
                        mHandler.sendEmptyMessage(SCAN_MEDIA_FILE_FINISH_INT);
                        break;
                    }
                }
                if (j==this.scanCount) {
                    Log.i(TAG,"send fail ");
                    //cx.sendBroadcast(new Intent(SCAN_MEDIA_FILE_FAIL));
                    mHandler.sendEmptyMessage(SCAN_MEDIA_FILE_FAIL_INT);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
       
       
    }
   
}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值