孙星

20169221 2016-2017-2《移动平台开发》第十二周学习总结

获取图片

1.从本地相册获取照片:

protected void getImageFromAlbum() {  
       Intent intent = new Intent(Intent.ACTION_PICK);  
       intent.setType("image/*");//相片类型  

2.从相机获取文件

Camera.java
通过源码可以发现,输出的图片有2个分支
如果你没有指定Intent里面的Extra参数,它就返回一个序列化(putExtra("data", bitmap))的Bitmap,从理论上来说,这样的代码写的很烂,属于Magic Number。
如果你指定了Intent里面的Extra参数MediaStore.EXTRA_OUTPUT,拍照后它就直接把bitmap写到了Uri里面了,返回是空
使用范围:获得很小的预览图,用于设置头像等地方。
返回示例:bitmap = data.getExtras().getParcelable("data");

public final static int REQUEST_IMAGE_CAPTURE = 1;

//start
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);

//receive
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode != RESULT_OK) {
      Log.d(TAG, "canceled or other exception!");
      return;
    }

    if (requestCode == REQUEST_IMAGE_CAPTURE) {
      Log.d(TAG, "REQUEST_IMAGE_CAPTURE");
      Bitmap bitmap;
      try {
     
        bitmap = data.getExtras().getParcelable("data"); 
        //TODO:do something with bitmap, Do NOT forget call Bitmap.recycler();
        mCameraImageview.setImageBitmap(bitmap);
      } catch (ClassCastException e){
           //do something with exceptions
        e.printStackTrace();
      } 
    }

  }

获得原始的拍照文件
使用范围:用于处理大的图片,比如使用滤镜,上传原始图像等操作,注意Uri不要用data私有目录,否则相机是写不进去的。

public final static int REQUEST_IMAGE_CAPTURE = 1;
Uri outputFileUri;

//start
  @OnClick(R.id.itemSelectCamera) void itemSelectCamera() {
    File file = FileUtils.createImageFile();
    outputFileUri = Uri.fromFile(file);
    Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(captureIntent, REQUEST_IMAGE_CAPTURE);
  }

//receive
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode != RESULT_OK) {
      Log.d(TAG, "canceled or other exception!");
      return;
    }

    if (requestCode == REQUEST_IMAGE_CAPTURE) {
      Log.d(TAG, "REQUEST_IMAGE_CAPTURE");
      //TODO:Use the Uri 
      Intent intent = new Intent(this, ImageFilterActivity.class);
      intent.setData(outputFileUri);
      startActivity(intent);
    }

  }

关于文件如何创建,目前我找到的就是这个最稳定了,写到SD卡根目录,data目录(Context.getXXDir())是私有目录,其它程序(比如Camera)是写不进去的

public class FileUtils {

  public static File createImageFile() {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    try {
      File image = File.createTempFile(imageFileName,  /* prefix */
          ".jpg",         /* suffix */
          Environment.getExternalStorageDirectory()      /* directory */);
      return image;
    } catch (IOException e) {
      //do noting
      return null;
    }
  }
}

制作视频

第一步:在Eclipse中创建一个名为AndroidCamera的Android工程,可参见Helloworld的例子;
第二步:在AndroidManifest.xml中添加使用Camera相关的声明如下:

<uses-feature android:name="android.hardware.camera" android:required="false" />  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    

第三步:编写AndroidCameraActivity类,如下:

import java.io.File;  
import java.text.SimpleDateFormat;  
import java.util.Date;  
import android.app.Activity;  
import android.content.Intent;  
import android.net.Uri;  
import android.os.Bundle;  
import android.os.Environment;  
import android.provider.MediaStore;  
import android.widget.Toast;  
  
public class AndroidCameraActivity extends Activity {  
    private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;    
        
    private Intent intent  = null;    
    private Uri fileUri    = null;    
    
    @Override    
    protected void onCreate(Bundle savedInstanceState) {    
        super.onCreate(savedInstanceState);    
        setContentView(R.layout.main);    
            
        intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);//create a intent to record video    
        fileUri = getOutputMediaFileUri(); // create a file Uri to save the video  
          
        // set the video file name  
        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);     
          
        // set the video quality high  
        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);   
  
        // start the video capture Intent  
        startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);    
    }    
    
    @Override    
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {    
        super.onActivityResult(requestCode, resultCode, data);    
            
        if(requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {    
            if (resultCode == RESULT_OK) {    
                // video captured and saved to fileUri specified in the Intent    
                Toast.makeText(this, "Video saved to:\n" +    
                         data.getData(),     
                         Toast.LENGTH_LONG).show();    
            } else if (resultCode == RESULT_CANCELED) {    
                // User cancelled the video capture    
            }    
        }    
    }    
        
    /** Create a File Uri for saving a video */    
    private static Uri getOutputMediaFileUri(){    
        //get the mobile Pictures directory  
        File picDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);  
  
        //get the current time  
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());   
          
        File videoFile = new File(picDir.getPath() + File.separator + "VIDEO_"+ timeStamp + ".mp4");    
    
        return Uri.fromFile(videoFile);  
    }    
}  

声音录制

MediaRecorder类详解
手机一般都有麦克风和摄像头,而Android系统就可以利用这些硬件来录制音视频了。
为了增加对录制音视频的支持,Android系统提供了一个MediaRecorder的类。
结构:

Java.lang.Object
android.media.MediaRecorder

与MediaPlayer类非常相似MediaRecorder也有它自己的状态图。下面是关于MediaRecorder的各个状态的介绍:
Initial:初始状态,当使用new()方法创建一个MediaRecorder对象或者调用了reset()方法时,该MediaRecorder对象处于Initial状态。在设定视频源或者音频源之后将转换为Initialized状态。另外,在除Released状态外的其它状态通过调用reset()方法都可以使MediaRecorder进入该状态。
Initialized:已初始化状态,可以通过在Initial状态调用setAudioSource()或setVideoSource()方法进入该状态。在这个状态可以通过setOutputFormat()方法设置输出格式,此时MediaRecorder转换为DataSourceConfigured状态。另外,通过reset()方法进入Initial状态。
DataSourceConfigured:数据源配置状态,这期间可以设定编码方式、输出文件、屏幕旋转、预览显示等等。可以在Initialized状态通过setOutputFormat()方法进入该状态。另外,可以通过reset()方法回到Initial状态,或者通过prepare()方法到达Prepared状态。
Prepared:就绪状态,在DataSourceConfigured状态通过prepare()方法进入该状态。在这个状态可以通过start()进入录制状态。另外,可以通过reset()方法回到Initialized状态。
Recording:录制状态,可以在Prepared状态通过调用start()方法进入该状态。另外,它可以通过stop()方法或reset()方法回到Initial状态。
Released:释放状态(官方文档给出的词叫做Idle state 空闲状态),可以通过在Initial状态调用release()方法来进入这个状态,这时将会释放所有和MediaRecorder对象绑定的资源。
Error:错误状态,当错误发生的时候进入这个状态,它可以通过reset()方法进入Initial状态。
提示:与MediaPlayer相似使用MediaRecorder录音录像时需要严格遵守状态图说明中的函数调用先后顺序,在不同的状态调用不同的函数,否则会出现异常。
实例描述了的创建过程

MediaRecorder recorder=newMediaRecorder();
 recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
 recorder.setOutputFile(PATH_NAME);
 recorder.prepare();
 recorder.start();  // Recording is now started
 ...
 recorder.stop();
 recorder.reset();  // You can reuse the object by going back to setAudioSource() step
 recorder.release();// Now the object cannot be reused
 

实践
使用MediaRecorder录制声音的:

  1. 创建 MediaRecorder 对象。
  2. 调用MediaRecorder对象的setAudioSource()方法设置声音来源,一般传入 MediaRecorder. AudioSource.MIC参数指定录制来自麦克风的声音。
  3. 调用MediaRecorder对象的setOutputFormat()设置所录制的音频文件的格式。
  4. 调用MediaRecorder 对象的setAudioEncoder()、setAudioEncodingBitRate(intbitRate)、 setAudioSamplingRate(int samplingRate)设置所录制的声音的编码格式、编码位率、采样率等, 这些参数将可以控制所录制的声音的品质、文件的大小。一般来说,声音品质越好,声音文件越大。
  5. 调用MediaRecorder的setOutputFile(Stringpath)方法设置录制的音频文件的保存位置。
  6. 调用MediaRecorder的prepare()方法准备录制。
  7. 调用MediaRecorder对象的start()方法开始录制。
  8. 录制完成,调用MediaRecorder对象的stop()方法停止录制,并调用release()方法释放资源。
<span style="font-size:18px;">package com.jph.recordsound;  
  
import java.io.File;  
import org.crazyit.sound.R;  
import android.app.Activity;  
import android.media.MediaRecorder;  
import android.os.Bundle;  
import android.os.Environment;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.ImageButton;  
import android.widget.Toast;  
  
  
public class RecordSound extends Activity  
    implements OnClickListener  
{  
    // 定义界面上的两个按钮  
    ImageButton record, stop;  
    // 系统的音频文件  
    File soundFile;  
    MediaRecorder mRecorder;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        // 获取程序界面中的两个按钮  
        record = (ImageButton) findViewById(R.id.record);  
        stop = (ImageButton) findViewById(R.id.stop);  
        // 为两个按钮的单击事件绑定监听器  
        record.setOnClickListener(this);  
        stop.setOnClickListener(this);  
    }  
  
    @Override  
    public void onDestroy()  
    {  
        if (soundFile != null && soundFile.exists())  
        {  
            // 停止录音  
            mRecorder.stop();  
            // 释放资源  
            mRecorder.release();  
            mRecorder = null;  
        }  
        super.onDestroy();  
    }  
  
    @Override  
    public void onClick(View source)  
    {  
        switch (source.getId())  
        {  
        // 单击录音按钮  
            case R.id.record:  
                if (!Environment.getExternalStorageState().equals(  
                    android.os.Environment.MEDIA_MOUNTED))  
                {  
                    Toast.makeText(RecordSound.this, "SD卡不存在,请插入SD卡!",  
                        Toast.LENGTH_SHORT).show();  
                    return;  
                }  
                try  
                {  
                    // 创建保存录音的音频文件  
                    soundFile = new File(Environment  
                        .getExternalStorageDirectory().getCanonicalFile()  
                        + "/sound.amr");  
                    mRecorder = new MediaRecorder();  
                    // 设置录音的声音来源  
                    mRecorder.setAudioSource(MediaRecorder  
                        .AudioSource.MIC);  
                    // 设置录制的声音的输出格式(必须在设置声音编码格式之前设置)  
                    mRecorder.setOutputFormat(MediaRecorder  
                        .OutputFormat.AMR_NB);  
                    // 设置声音编码的格式  
                    mRecorder.setAudioEncoder(MediaRecorder  
                        .AudioEncoder.AMR_NB);  
                    mRecorder.setOutputFile(soundFile.getAbsolutePath());  
                    mRecorder.prepare();  
                    // 开始录音  
                    mRecorder.start();  //①  
                }  
                catch (Exception e)  
                {  
                    e.printStackTrace();  
                }  
                break;  
            // 单击停止按钮  
            case R.id.stop:  
                if (soundFile != null && soundFile.exists())  
                {  
                    // 停止录音  
                    mRecorder.stop();  //②  
                    // 释放资源  
                    mRecorder.release();  //③  
                    mRecorder = null;  
                }  
                break;  
        }  
    }  
}</span>  

结果图

posted on 2017-05-21 23:47  20169221孙星  阅读(138)  评论(0编辑  收藏  举报

导航