一.变量声明
private AudioRecord audioRecord = null; private static int frequency = 44100; private static int channel = AudioFormat.CHANNEL_IN_STEREO;// 设置声道 private static int encodingBitRate = AudioFormat.ENCODING_PCM_16BIT;// 设置编码 private static final int recorder_bpp = 16; private int recBufSize = 0; private int playBufSize = 0; private boolean isRecording = false;// 录音标志位 private String tempFilePath;// 临时文件的路径 private String saveFilePath;// 保存文件的路径 private static final String saveFold = "Audio123";// 保存的文件夹名 private static final String temp_file = "record_temp.raw";// 零时文件名 private Thread recThread = null;//录音线程
tempFilePath = SDCardHelp.getFilePath(saveFold) + "/" + temp_file; String fileName = DateHelp.getFormateDate(3); saveFilePath = SDCardHelp.getFilePath(saveFold) + "/" + fileName + ".wav";
// 开始录音 private void startRec() { recBufSize = AudioRecord.getMinBufferSize(frequency, channel, encodingBitRate); audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, channel, encodingBitRate, recBufSize); audioRecord.startRecording(); isRecording = true; recThread = new Thread(new Runnable() { public void run() { writeAudioDataToFile(); } }, "AudioRecorder Thread"); recThread.start(); } // 将音频数据写入文件 private void writeAudioDataToFile() { byte data[] = new byte[recBufSize]; FileOutputStream os = null; try { os = new FileOutputStream(tempFilePath); } catch (FileNotFoundException e) { e.printStackTrace(); } int read = 0; if (null != os) { while (isRecording) { read = audioRecord.read(data, 0, recBufSize); if (AudioRecord.ERROR_INVALID_OPERATION != read) { try { os.write(data); } catch (IOException e) { e.printStackTrace(); } } } try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } private void stopRecording() { if (null != audioRecord) { isRecording = false; audioRecord.stop(); audioRecord.release(); audioRecord = null; recThread = null; } String fileName = DateHelp.getFormateDate(3); saveFilePath = SDCardHelp.getFilePath(saveFold) + "/" + fileName + ".wav"; copyWaveFile(tempFilePath, saveFilePath); deleteTempFile(); } // 删除临时文件 private void deleteTempFile() { File file = new File(tempFilePath); file.delete(); } private void copyWaveFile(String inFilename, String outFilename) { FileInputStream in = null; FileOutputStream out = null; long totalAudioLen = 0; long totalDataLen = totalAudioLen + 36; long longSampleRate = frequency; int channels = 2; long byteRate = recorder_bpp * frequency * channels / 8; byte[] data = new byte[recBufSize]; try { in = new FileInputStream(inFilename); out = new FileOutputStream(outFilename); totalAudioLen = in.getChannel().size(); totalDataLen = totalAudioLen + 36; WriteWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate); while (in.read(data) != -1) { out.write(data); } in.close(); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate) throws IOException { byte[] header = new byte[44]; header[0] = 'R'; // RIFF/WAVE header header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; header[4] = (byte) (totalDataLen & 0xff); header[5] = (byte) ((totalDataLen >> 8) & 0xff); header[6] = (byte) ((totalDataLen >> 16) & 0xff); header[7] = (byte) ((totalDataLen >> 24) & 0xff); header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; header[12] = 'f'; // 'fmt ' chunk header[13] = 'm'; header[14] = 't'; header[15] = ' '; header[16] = 16; // 4 bytes: size of 'fmt ' chunk header[17] = 0; header[18] = 0; header[19] = 0; header[20] = 1; // format = 1 header[21] = 0; header[22] = (byte) channels; header[23] = 0; header[24] = (byte) (longSampleRate & 0xff); header[25] = (byte) ((longSampleRate >> 8) & 0xff); header[26] = (byte) ((longSampleRate >> 16) & 0xff); header[27] = (byte) ((longSampleRate >> 24) & 0xff); header[28] = (byte) (byteRate & 0xff); header[29] = (byte) ((byteRate >> 8) & 0xff); header[30] = (byte) ((byteRate >> 16) & 0xff); header[31] = (byte) ((byteRate >> 24) & 0xff); header[32] = (byte) (2 * 16 / 8); // block align header[33] = 0; header[34] = recorder_bpp; // bits per sample header[35] = 0; header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte) (totalAudioLen & 0xff); header[41] = (byte) ((totalAudioLen >> 8) & 0xff); header[42] = (byte) ((totalAudioLen >> 16) & 0xff); header[43] = (byte) ((totalAudioLen >> 24) & 0xff); out.write(header, 0, 44); }
【翻译】(49)category元素
see
http://developer.android.com/guide/topics/manifest/category-element.html
原文见
http://developer.android.com/guide/topics/manifest/category-element.html
-------------------------------
<category>
category元素
-------------------------------
* syntax:
* 语法:
-------------------------------
<category android:name="string" />
-------------------------------
* contained in:
* 被包含在:
<intent-filter>
* description:
* 描述:
Adds a category name to an intent filter. See Intents and Intent Filters for details on intent filters and the role of category specifications within a filter.
添加一个分类名称到一个意图过滤器。参见意图与意图过滤器以获得关于意图过滤器和在过滤器中分类指定的作用的细节。
* attributes:
* 属性:
* android:name
The name of the category. Standard categories are defined in the Intent class as CATEGORY_name constants. The name assigned here can be derived from those constants by prefixing "android.intent.category." to the name that follows CATEGORY_. For example, the string value for CATEGORY_LAUNCHER is "android.intent.category.LAUNCHER".
分类的名称。标准分类被定义在Intent类中作为CATEGORY_<名称>常量。这里赋予的名称可以从那些前缀为"android.intent.category."的常量中派生成CATEGORY_前缀的名称。例如,CATEGORY_LAUNCHER的字符串值是"android.intent.category.LAUNCHER"。
Custom categories should use the package name as a prefix, to ensure that they are unique.
自定义分类应该使用包名作为前缀,以确保它们是唯一的。
* introduced in:
* 引入:
API Level 1
API级别1
* see also:
* 另见:
<action>
<data>
Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.
除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。
Android 4.0 r1 - 10 Feb 2012 0:44
-------------------------------
Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
(此页部分内容基于Android开源项目,以及使用根据创作公共2.5来源许可证描述的条款进行修改)
(本人翻译质量欠佳,请以官方最新内容为准,或者参考其它翻译版本:
* ソフトウェア技術ドキュメントを勝手に翻訳
http://www.techdoctranslator.com/android
* Ley's Blog
http://leybreeze.com/blog/
* 农民伯伯
http://www.cnblogs.com/over140/
* Android中文翻译组
http://androidbox.sinaapp.com/
)
package com; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.graphics.Bitmap.CompressFormat; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import com.cgt.camera.R; import com.lilin.util.GetSysDate; import com.lilin.util.SDCardHelp; import com.lilin.util.ShowMsg; /** * * @author lilin * @date 2011-9-3 下午12:22:10 * @ClassName: Main * @Description: TODO */ public class TakePhotoView extends Activity implements SurfaceHolder.Callback, OnClickListener, PictureCallback { private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private Camera camera;// 相机 private Camera.Parameters cameraParam;// 相机参数 private Camera.Size cameraSize;// 相机大小 private boolean isPreViewing = true; private boolean isHasSurface; byte[] data; Button take_btn;// 拍照 ImageView preView_iv;// 预览 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFormat(PixelFormat.TRANSLUCENT); requestWindowFeature(Window.FEATURE_NO_TITLE);// 无标题 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 全屏 setContentView(R.layout.takephotoview); initView(); } // 界面创建时被调用,一般是用来,打开相机,设置预览 public void surfaceCreated(SurfaceHolder holder) { if (camera == null) { camera = Camera.open();// 不能放在构造函数里,否则产生不了预览效果 try { camera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } isHasSurface = true; } } // 在界面尺寸改变时被调用,设置相机的参数(大小,格式) public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (isPreViewing) { isPreViewing = false; camera.stopPreview(); } cameraParam = camera.getParameters(); // 这项设置可以解决部分机型报setPreview()的错 cameraParam.setPreviewSize(w, h); cameraParam.setPictureFormat(PixelFormat.JPEG);// 图片格式 camera.setParameters(cameraParam);// 设置参数 if (!isPreViewing) { camera.startPreview(); isPreViewing = true; } } // 捕捉相机拍到的图片 public void onPictureTaken(byte[] _data, Camera camera) { // 得到图片data Bitmap bitmap = BitmapFactory.decodeByteArray(_data, 0, _data.length); savepicture(bitmap, GetSysDate.getFormateDate(1));// 保存图片 if (!isPreViewing) { camera.startPreview(); isPreViewing = true; } else { isPreViewing = false; camera.stopPreview(); camera.startPreview();// 开始预览 isPreViewing = true; } } public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { if (isPreViewing) { camera.stopPreview(); isPreViewing = false; } camera.release(); camera = null; } isHasSurface = false; } // 保存图片 public void savepicture(Bitmap bitmap, String formateDate) { try { if (!SDCardHelp.getFileSavePath(getString(R.string.pic_savepath)) .toString().equals(null)) { File file = new File(SDCardHelp .getFileSavePath(getString(R.string.pic_savepath)), formateDate + ".jpg");// 创建图片文件 FileOutputStream outStream = new FileOutputStream(file); bitmap.compress(CompressFormat.JPEG, 100, outStream); outStream.close(); take_btn.setEnabled(true); // 设置拍照按钮可用 take_btn.setBackgroundResource(R.drawable.take_picture1); } else { ShowMsg.showToast(getApplicationContext(), "请插入内存卡!"); } } catch (Exception e) { e.printStackTrace(); } } // 获取最佳预览视图 public Camera.Size getBestPreviewSize(Camera.Parameters parameters, int w, int h) { Camera.Size result = null; for (Camera.Size size : parameters.getSupportedPreviewSizes()) { if (size.width <= w && size.height <= h) { if (null == result) result = size; else { int resultDelta = w - result.width + h - result.height; int newDelta = w - size.width + h - size.height; if (newDelta < resultDelta) result = size; } } } return result; } public void onClick(View v) { switch (v.getId()) { case R.id.takepic_btn:// 拍照 // 自动对焦 camera.takePicture(null, null, this); take_btn.setEnabled(false); take_btn.setBackgroundResource(R.drawable.take_picture2); break; default: break; } } public void initView() { surfaceView = (SurfaceView) findViewById(R.id.surface_camera); take_btn = (Button) findViewById(R.id.takepic_btn); preView_iv = (ImageView) findViewById(R.id.myImageView); take_btn.setOnClickListener(this); } protected void onPause() { System.out.println("onpause"); super.onPause(); } protected void onResume() { surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); super.onResume(); } }