Android Tutorial 第四堂(1)使用照相機與麥克風
|
Android Tutorial系列專欄已經改版為「Android 6 Tutorial」,從2015/10/22開始連載,請點選這裡: https://www.codedata.com.tw/mobile/android-6-tutorial-1-1/ Android Tutorial 第三堂(3)Android 內建的 SQLite 資料庫 << 前情 這一章在處理相片與錄音檔名稱的時候有錯誤,建議在完成這一章的內容以後,再參考錯誤修正:4-1 使用照相機與麥克風修正錯誤。 現在行動裝置的硬體設備技術已經越來越好了,螢幕的尺寸不斷的增加,提供使用者清楚又美觀的畫面。觸控螢幕也幾乎是目前行動裝置的標準設備,使用觸控的方式操作應用程式快速又方便。Android系統內建的音樂播放應用程式,也可以讓行動裝置成為隨身的音樂播放設備。還有畫素也越來越高的照像功能,一台行動裝置幾乎可以應付所有的需求。 行動裝置提供高畫質的攝影鏡頭,讓使用者隨時可以拍攝照片與錄影,也幾乎已經是行動裝置基本的設備與功能了。使用Android系統內建的API與元件,可以在應用程式需要的時候,讓使用者拍攝照片與錄影,並且把照片或影片檔案儲存在指定的位置。例如在記事本應用程式中,可以加入照片與錄影備忘的功能。 應用程式需要錄音的時候,可以使用內建的API執行錄音的工作,並且把錄音完成的檔案儲存在指定的位置,例如在記事本應用程式中,可以加入錄製語音備忘的功能,讓使用者可以隨時查詢與播放這些錄音資訊。 這一章為記事資料加入照相與錄音的功能,讓這個應用程式的功能可以更完整,使用者可以在新增或修改記事資料的時候,啟動相機拍照,還有使用麥克風錄製語音備忘。 12-1 使用相機拍攝照片不論是行動電話或平板電腦,幾乎都有高畫質的攝錄鏡頭設備,讓使用者可以隨時拍攝與錄影。加入拍攝照片的功能可以讓應用程式的功能更完整,例如在記事本應用程式加入拍照的功能,記錄影像會比文字更清楚與方便。 應用程式需要執行拍照的功能,可以啟動系統相機元件執行拍照的工作,它的系統Action名稱變數是「MediaStore.ACTIONIMAGECAPTURE」,使用這個Action名稱建立好的Intent物件,可以呼叫putExtra方法加入照片檔案儲存位置的設定資料,資料的名稱是「MediaStore.EXTRA_OUTPUT」,如果沒有指定的話,會使用系統預設的名稱儲存在預設的位置。 應用程式要執行拍照的功能,裝置必須有攝錄鏡頭的設備才可以正確的執行,所以需要在應用程式設定檔中加入硬體設備需求的設定。如果需要儲存照片檔案到外部儲存設備,例如記憶卡,需要在應用程式設定檔中加入授權設定: <!-- 需要攝錄鏡頭設備 -->
<uses-feature android:name="android.hardware.camera" />
<!-- 寫入外部儲存設備 -->
<uses-permission android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"/>
Android模擬裝置也可以測試相機的功能,不過要先確認模擬裝置的設定,關閉已經啟動的模擬裝置,在Android Studio選擇功能表「Tools -> Android -> AVD Manager」,選擇模擬裝置的編輯圖示: 在模擬裝置編輯視窗選擇「Show Advanced Settings」: 如果你的電腦沒有連接WebCam,在「Front」與「Back」選擇「Emulated」。如果電已經連接WebCam,就可以選擇「Webcam0」。完成設定後選擇「Finish」: 回到AVD Manager視窗後,選擇模擬裝置的啟動圖示: 模擬裝置啟動以後,開啟「照相」應用程式,就可以看到模擬照相機的畫面: 因為記事元件的畫面加入照片以後,在螢幕比較小的裝置運作時,畫面會超過螢幕的範圍,所以需要調整畫面的設計。另外也要加入顯示照片用的ImageView元件。開啟「res/layout/activity_item.xml」,參考下列的內容修改這個畫面配置檔: <?xml version="1.0" encoding="utf-8"?>
<!-- 使用ScrollView為最外層的元件 -->
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 刪除xmlns:android的設定 -->
<TableLayout
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="1"
tools:context="net.macdidi.myandroidtutorial.ItemActivity">
<TableRow>
...
</TableRow>
<TableRow>
...
</TableRow>
<!-- 顯示圖片 -->
<ImageView
android:id="@+id/picture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/retangle_drawable"
android:padding="6sp"
android:layout_margin="2sp"
android:visibility="invisible" />
<TableLayout ...>
<TableRow>
...
</TableRow>
</TableLayout>
<TableLayout ...>
<TableRow>
...
</TableRow>
</TableLayout>
</TableLayout>
<!-- ScrollView的結束標籤 -->
</ScrollView>
因為需要儲存照片與錄音檔案,所以撰寫一個檔案公用類別。在「net.macdidi.myandroidtutorial」套件按滑鼠右鍵,選擇「New -> Java CLass」,在Name輸入「FileUtil」後選擇「OK」。參考下列的內容完成這個程式碼: package net.macdidi.myandroidtutorial;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;
import android.widget.ImageView;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileUtil {
// 應用程式儲存檔案的目錄
public static final String APP_DIR = "androidtutorial";
// 外部儲存設備是否可寫入
public static boolean isExternalStorageWritable() {
// 取得目前外部儲存設備的狀態
String state = Environment.getExternalStorageState();
// 判斷是否可寫入
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
// 外部儲存設備是否可讀取
public static boolean isExternalStorageReadable() {
// 取得目前外部儲存設備的狀態
String state = Environment.getExternalStorageState();
// 判斷是否可讀取
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
// 建立並傳回在公用相簿下參數指定的路徑
public static File getPublicAlbumStorageDir(String albumName) {
// 取得公用的照片路徑
File pictures = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
// 準備在照片路徑下建立一個指定的路徑
File file = new File(pictures, albumName);
// 如果建立路徑不成功
if (!file.mkdirs()) {
Log.e("getAlbumStorageDir", "Directory not created");
}
return file;
}
// 建立並傳回在應用程式專用相簿下參數指定的路徑
public static File getAlbumStorageDir(Context context, String albumName) {
// 取得應用程式專用的照片路徑
File pictures = context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES);
// 準備在照片路徑下建立一個指定的路徑
File file = new File(pictures, albumName);
// 如果建立路徑不成功
if (!file.mkdirs()) {
Log.e("getAlbumStorageDir", "Directory not created");
}
return file;
}
// 建立並傳回外部儲存媒體參數指定的路徑
public static File getExternalStorageDir(String dir) {
File result = new File(
Environment.getExternalStorageDirectory(), dir);
if (!isExternalStorageWritable()) {
return null;
}
if (!result.exists() && !result.mkdirs()) {
return null;
}
return result;
}
// 讀取指定的照片檔案名稱設定給ImageView元件
public static void fileToImageView(String fileName, ImageView imageView) {
if (new File(fileName).exists()) {
Bitmap bitmap = BitmapFactory.decodeFile(fileName);
imageView.setImageBitmap(bitmap);
}
else {
Log.e("fileToImageView", fileName + " not found.");
}
}
// 產生唯一的檔案名稱
public static String getUniqueFileName() {
// 使用年月日_時分秒格式為檔案名稱
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
return sdf.format(new Date());
}
}
開啟在「net.macdidi.myandroidtutorial」套件下的「ItemActivity」類別,加入照相功能需要的欄位變數: // 檔案名稱 private String fileName; // 照片 private ImageView picture; 同樣在「ItemActivity」類別,找到「processViews」方法,參考下列的程式碼,加入取得顯示照片ImageView元件的程式碼: private void processViews() {
title_text = (EditText) findViewById(R.id.title_text);
content_text = (EditText) findViewById(R.id.content_text);
// 取得顯示照片的ImageView元件
picture = (ImageView) findViewById(R.id.picture);
}
同樣在「ItemActivity」類別,找到「clickFunction」方法,參考下列的程式碼,加入啟動相機元件的程式碼: public void clickFunction(View view) {
int id = view.getId();
switch (id) {
case R.id.take_picture:
// 啟動相機元件用的Intent物件
Intent intentCamera =
new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 照片檔案名稱
File pictureFile = configFileName("P", ".jpg");
Uri uri = Uri.fromFile(pictureFile);
// 設定檔案名稱
intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, uri);
// 啟動相機元件
startActivityForResult(intentCamera, START_CAMERA);
break;
...
}
}
private File configFileName(String prefix, String extension) {
// 如果記事資料已經有檔案名稱
if (item.getFileName() != null && item.getFileName().length() > 0) {
fileName = item.getFileName();
}
// 產生檔案名稱
else {
fileName = FileUtil.getUniqueFileName();
}
return new File(FileUtil.getExternalStorageDir(FileUtil.APP_DIR),
prefix + fileName + extension);
}
同樣在「ItemActivity」類別,找到「onActivityResult」方法,參考下列的程式碼,處理完成照相工作後的程式碼: @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
// 照像
case START_CAMERA:
// 設定照片檔案名稱
item.setFileName(fileName);
break;
...
}
}
}
同樣在「ItemActivity」類別,新增覆寫「onResume」方法的程式碼,執行顯示照片的工作: @Override
protected void onResume() {
super.onResume();
// 如果有檔案名稱
if (item.getFileName() != null && item.getFileName().length() > 0) {
// 照片檔案物件
File file = configFileName("P", ".jpg");
// 如果照片檔案存在
if (file.exists()) {
// 顯示照片元件
picture.setVisibility(View.VISIBLE);
// 設定照片
FileUtil.fileToImageView(file.getAbsolutePath(), picture);
}
}
}
完成照相功能的工作了,執行應用程式,新增一個記事資料後選擇照相功能: 畫面出現像這樣的相機模擬畫面,選擇照像按鈕: 選擇確定按鈕: 記事資料顯示拍好的照片,儲存記事資料後也會儲存照片: 12-2 錄製語音備忘在行動裝置的應用程式使用錄音功能,可以讓很多工作變得更方便,例如語音備忘錄的功能,可以省掉很多輸入文字的時間。如果應用程式需要執行錄音的工作,使用宣告在「android.media」套件下的「MediaRecorder」類別,應用程式可以設定錄音的來源、輸出格式、編碼和儲存檔案的位置。這些是執行設定與錄音的方法,要特別注意在程式碼中呼叫它們的順序:
如果應用程式需要使用裝置的錄音設備,必須在應用程式設定檔「AndroidManifest.xml」加入授權的設定: <uses-permission android:name="android.permission.RECORD_AUDIO"/> 加入錄音功能的記事應用程式,可以讓使用者選擇錄音功能按鈕,啟動一個負責錄音的Activity元件,按下錄音按鈕就可以開始錄音: 錄音的時候,錄音按鈕會切換為紅色的圖示,錄音的音量變化會在右側顯示: 設計錄音元件的畫面配置檔,使用的圖形資源可以在GitHub中取得,需要「recorddardicon.png」與「recordredicon.png」兩個圖示檔案。開啟「res/values/strings.xml」,加入這個元件需要的文字資源: <string name="title_record">語音備忘</string> 在「res/layout」目錄按滑鼠右鍵,選擇「New -> Layout resrouce file」,在File name輸入「activity_record」候選擇「OK」。參考下列的內容,完成這個畫面資源的設計: <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/retangle_drawable"
android:layout_margin="6sp"
android:padding="6sp">
<ImageButton
android:id="@+id/record_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/record_sound_icon"
android:onClick="clickRecord" />
<ProgressBar
android:id="@+id/record_volumn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:max="15"
style="@android:style/Widget.ProgressBar.Horizontal" />
</LinearLayout>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="*">
<TableRow>
<Button
android:text="@android:string/cancel"
android:onClick="onSubmit" />
<Button
android:id="@+id/record_ok"
android:text="@android:string/ok"
android:onClick="onSubmit" />
</TableRow>
</TableLayout>
</LinearLayout>
在「net.macdidi.myandroidtutorial」套件按滑鼠右鍵,選擇「New -> Java CLass」,在Name輸入「RecordActivity」後選擇「OK」。參考下列的內容完成這個Activity元件的程式碼:(這裡提供的設計包含顯示錄音中的音量,你可以考慮移除這個部份的程式碼,這個元件的設計就會比較簡單一些) package net.macdidi.myandroidtutorial;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import java.io.IOException;
public class RecordActivity extends Activity {
private ImageButton record_button;
private boolean isRecording = false;
private ProgressBar record_volumn;
private MyRecoder myRecoder;
private String fileName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record);
processViews();
// 讀取檔案名稱
Intent intent = getIntent();
fileName = intent.getStringExtra("fileName");
}
public void onSubmit(View view) {
if (isRecording) {
// 停止錄音
myRecoder.stop();
}
// 確定
if (view.getId() == R.id.record_ok) {
Intent result = getIntent();
setResult(Activity.RESULT_OK, result);
}
finish();
}
private void processViews() {
record_button = (ImageButton) findViewById(R.id.record_button);
record_volumn = (ProgressBar) findViewById(R.id.record_volumn);
// 隱藏狀態列ProgressBar
setProgressBarIndeterminateVisibility(false);
}
public void clickRecord(View view) {
// 切換
isRecording = !isRecording;
// 開始錄音
if (isRecording) {
// 設定按鈕圖示為錄音中
record_button.setImageResource(R.drawable.record_red_icon);
// 建立錄音物件
myRecoder = new MyRecoder(fileName);
// 開始錄音
myRecoder.start();
// 建立並執行顯示麥克風音量的AsyncTask物件
new MicLevelTask().execute();
}
// 停止錄音
else {
// 設定按鈕圖示為停止錄音
record_button.setImageResource(R.drawable.record_dark_icon);
// 麥克風音量歸零
record_volumn.setProgress(0);
// 停止錄音
myRecoder.stop();
}
}
// 在錄音過程中顯示麥克風音量
private class MicLevelTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... args) {
while (isRecording) {
publishProgress();
try {
Thread.sleep(200);
}
catch (InterruptedException e) {
Log.d("RecordActivity", e.toString());
}
}
return null;
}
@Override
protected void onProgressUpdate(Void... values) {
record_volumn.setProgress((int) myRecoder.getAmplitudeEMA());
}
}
// 執行錄音並且可以取得麥克風音量的錄音物件
private class MyRecoder {
private static final double EMA_FILTER = 0.6;
private MediaRecorder recorder = null;
private double mEMA = 0.0;
private String output;
// 建立錄音物件,參數為錄音儲存的位置與檔名
MyRecoder(String output) {
this.output = output;
}
// 開始錄音
public void start() {
if (recorder == null) {
// 建立錄音用的MediaRecorder物件
recorder = new MediaRecorder();
// 設定錄音來源為麥克風,必須在setOutputFormat方法之前呼叫
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 設定輸出格式為3GP壓縮格式,必須在setAudioSource方法之後,
// 在prepare方法之前呼叫
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
// 設定錄音的編碼方式,必須在setOutputFormat方法之後,
// 在prepare方法之前呼叫
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
// 設定輸出的檔案名稱,必須在setOutputFormat方法之後,
// 在prepare方法之前呼叫
recorder.setOutputFile(output);
try {
// 準備執行錄音工作,必須在所有設定之後呼叫
recorder.prepare();
}
catch (IOException e) {
Log.d("RecordActivity", e.toString());
}
// 開始錄音
recorder.start();
mEMA = 0.0;
}
}
// 停止錄音
public void stop() {
if (recorder != null) {
// 停止錄音
recorder.stop();
// 清除錄音資源
recorder.release();
recorder = null;
}
}
public double getAmplitude() {
if (recorder != null)
return (recorder.getMaxAmplitude() / 2700.0);
else
return 0;
}
// 取得麥克風音量
public double getAmplitudeEMA() {
double amp = getAmplitude();
mEMA = EMA_FILTER * amp + (1.0 - EMA_FILTER) * mEMA;
return mEMA;
}
}
}
開啟應用程式設定檔「AndroidManifest.xml」,加入錄音元件的設定: <!-- 錄音元件 -->
<activity
android:name="net.macdidi.myandroidtutorial.RecordActivity"
android:theme="@android:style/Theme.Dialog"
android:label="@string/title_record"/>
完成錄音元件的設計後,開啟在「net.macdidi.myandroidtutorial」套件下的「ItemActivity」類別,找到「clickFunction」方法,加入啟動錄音元件的程式碼,還有負責錄音的goToRecord方法: public void clickFunction(View view) {
int id = view.getId();
switch (id) {
case R.id.take_picture:
...
case R.id.record_sound:
// 錄音檔案名稱
final File recordFile = configFileName("R", ".mp3");
// 如果已經有錄音檔,詢問播放或重新錄製
if (recordFile.exists()) {
// 詢問播放還是重新錄製的對話框
AlertDialog.Builder d = new AlertDialog.Builder(this);
d.setTitle(R.string.title_record)
.setCancelable(false);
d.setPositiveButton(R.string.record_play,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 播放
// 在後面的說明才會處理
}
});
d.setNeutralButton(R.string.record_new,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
goToRecord(recordFile);
}
});
d.setNegativeButton(android.R.string.cancel, null);
// 顯示對話框
d.show();
}
// 如果沒有錄音檔,啟動錄音元件
else {
goToRecord(recordFile);
}
break;
...
}
}
private void goToRecord(File recordFile) {
// 錄音
Intent recordIntent = new Intent(this, RecordActivity.class);
recordIntent.putExtra("fileName", recordFile.getAbsolutePath());
startActivityForResult(recordIntent, START_RECORD);
}
為記事資料完成錄音的功能了,在完成後面的播放功能後,再一起執行測試的工作。 12-3 播放語音備忘在前面已經完成的功能,如果使用者選擇的記事資料已經錄製過語音備忘,應用程式可以選擇播放或是重新錄製: 使用者選擇播放功能,應用程式啟動播放語音備忘元件,這個元件提供播放、暫停與停止三個功能按鈕: 現在設計錄音元件的畫面配置檔,使用的圖形資源可以在GitHub中取得,需要「playicon.png」、「pauseicon」與「stop_icon.png」三個圖示檔案。開啟「res/values/strings.xml」,加入這個元件需要的文字資源: <string name="title_play">播放語音備忘</string> <string name="record_play">播放</string> <string name="record_new">重新錄製</string> 在「res/layout」目錄按滑鼠右鍵,選擇「New -> Layout resrouce file」,在File name輸入「activity_play」候選擇「OK」。參考下列的內容,完成這個畫面資源的設計: <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/retangle_drawable"
android:layout_margin="6sp"
android:padding="6sp" >
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/play_icon"
android:onClick="clickPlay" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/pause_icon"
android:onClick="clickPause" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/stop_icon"
android:onClick="clickStop" />
<SeekBar
android:id="@+id/control"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginTop="8sp" />
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/ok_add_teim"
android:text="@android:string/ok"
android:onClick="onSubmit" />
</LinearLayout>
在「net.macdidi.myandroidtutorial」套件按滑鼠右鍵,選擇「New -> Java CLass」,在Name輸入「PlayActivity」後選擇「OK」。參考下列的內容完成這個Activity元件的程式碼: package net.macdidi.myandroidtutorial;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
public class PlayActivity extends Activity {
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
Intent intent = getIntent();
String fileName = intent.getStringExtra("fileName");
// 建立指定資源的MediaPlayer物件
Uri uri = Uri.parse(fileName);
mediaPlayer = MediaPlayer.create(this, uri);
}
@Override
protected void onStop() {
if (mediaPlayer.isPlaying()) {
// 停止播放
mediaPlayer.stop();
}
// 清除MediaPlayer物件
mediaPlayer.release();
super.onStop();
}
public void onSubmit(View view) {
// 結束Activity元件
finish();
}
public void clickPlay(View view) {
// 開始播放
mediaPlayer.start();
}
public void clickPause(View view) {
// 暫停播放
mediaPlayer.pause();
}
public void clickStop(View view) {
// 停止播放
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
// 回到開始的位置
mediaPlayer.seekTo(0);
}
}
開啟應用程式設定檔「AndroidManifest.xml」,加入這個Activity元件的設定: <!-- 播放元件 -->
<activity
android:name="net.macdidi.myandroidtutorial.PlayActivity"
android:theme="@android:style/Theme.Dialog"
android:label="@string/title_play"/>
完成元件的設計後,開啟在「net.macdidi.myandroidtutorial」套件下的「ItemActivity」類別,找到「clickFunction」方法,加入啟動這個元件的程式碼: public void clickFunction(View view) {
int id = view.getId();
switch (id) {
case R.id.take_picture:
...
case R.id.record_sound:
// 錄音檔案名稱
final File recordFile = configFileName("R", ".mp3");
// 如果已經有錄音檔,詢問播放或重新錄製
if (recordFile.exists()) {
// 詢問播放還是重新錄製的對話框
AlertDialog.Builder d = new AlertDialog.Builder(this);
d.setTitle(R.string.title_record)
.setCancelable(false);
d.setPositiveButton(R.string.record_play,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 播放
Intent playIntent = new Intent(
ItemActivity.this, PlayActivity.class);
playIntent.putExtra("fileName",
recordFile.getAbsolutePath());
startActivity(playIntent);
}
});
d.setNeutralButton(R.string.record_new,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
goToRecord(recordFile);
}
});
d.setNegativeButton(android.R.string.cancel, null);
// 顯示對話框
d.show();
}
// 如果沒有錄音檔,啟動錄音元件
else {
goToRecord(recordFile);
}
break;
...
}
}
同樣在「net.macdidi.myandroidtutorial」套件下的「ItemActivity」類別,找到「onActivityResult」方法,加入設定檔案名稱的程式碼: @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
...
case START_RECORD:
// 設定錄音檔案名稱
item.setFileName(fileName);
break;
...
}
}
}
完成這一章所有的工作了,錄音與播放的功能比較建議在實體的裝置上測試,試試看加入的功能是不是都可以正確的運作。 課程相關的檔案都可以GitHub瀏覽與下載。 後續 >> Android Tutorial 第四堂(2)設計地圖應用程式 – Google Maps Android API v2 |

Java 學習之路












https://github.com/macdidi5/AndroidTutorial




jimlingandy
03/05老師你好, 我是Android新手。
最近使用Android Studio 配合zxing lib 使用,想把掃瞄的畫面改為直式(zxing 預設為橫式), 請教老師如何使用Android Studio修改 zxing 為直式。
tpadcps999
03/09老師你好! 你的文章真的對我們剛入門Andriod的新手很有幫助 謝謝!
請問如果我需要直接MIC接收聲音訊號然後Realtime播放出來
(類似擴音機)
我開如何撰寫呢 一樣用media 的IDE嗎