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录制声音的:
- 创建 MediaRecorder 对象。
- 调用MediaRecorder对象的setAudioSource()方法设置声音来源,一般传入 MediaRecorder. AudioSource.MIC参数指定录制来自麦克风的声音。
- 调用MediaRecorder对象的setOutputFormat()设置所录制的音频文件的格式。
- 调用MediaRecorder 对象的setAudioEncoder()、setAudioEncodingBitRate(intbitRate)、 setAudioSamplingRate(int samplingRate)设置所录制的声音的编码格式、编码位率、采样率等, 这些参数将可以控制所录制的声音的品质、文件的大小。一般来说,声音品质越好,声音文件越大。
- 调用MediaRecorder的setOutputFile(Stringpath)方法设置录制的音频文件的保存位置。
- 调用MediaRecorder的prepare()方法准备录制。
- 调用MediaRecorder对象的start()方法开始录制。
- 录制完成,调用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) 编辑 收藏 举报