編輯:關於Android編程
記事本涉及到的僅僅是對string 的存儲,而且在讀取上並不存在什麼難點,直接用textview顯示便可以了。需要做的主要是使用SQLite對數據進行一個整理。
而錄音筆需要考慮的就相對較多了:比如錄音時中斷,錄音時用戶點擊播放按鈕;未錄音,用戶點擊停止按鈕;在錄音或者播放時關閉activity;listview的item中需要為button設置不同的點擊效果等等。
為了便於新手學習,在此還是羅列一下涉及的主要知識點:
遇到的問題:
在listview item中的button控件可以獲得焦點時,直接為listview設置item長按事件的監聽。出現了listview的item長按事件無效的情況。
解決方法:
直接在Baseadapter中對該item的布局進行長按事件的監聽(在筆者demo中是linearlayout),也就是說對item中button的父布局進行長按事件的監聽。
效果:
MainActivity:
package com.example.recorder; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import java.io.File; import java.io.IOException; public class MainActivity extends Activity implements OnClickListener { private Button start; private Button stop; private ListView listView; ShowRecorderAdpter showRecord; // 錄音文件播放 // 錄音 // 音頻文件保存地址 private MediaPlayer myPlayer; private MediaRecorder myRecorder = null; private String path; private File saveFilePath; // 所錄音的文件名 String[] listFile = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化控件 InitView(); } private void InitView() { start = (Button) findViewById(R.id.start); stop = (Button) findViewById(R.id.stop); listView = (ListView) findViewById(R.id.list); myPlayer = new MediaPlayer(); showRecord = new ShowRecorderAdpter(); //如果手機有sd卡 if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { try { path = Environment.getExternalStorageDirectory() .getCanonicalPath().toString() + "/MyRecorders"; File files = new File(path); if (!files.exists()) { //如果有沒有文件夾就創建文件夾 files.mkdir(); } listFile = files.list(); } catch (IOException e) { e.printStackTrace(); } } start.setOnClickListener(this); stop.setOnClickListener(this); listView.setAdapter(showRecord); } //由於在item中涉及到了控件的點擊效果,所以采用BaseAdapter class ShowRecorderAdpter extends BaseAdapter { @Override public int getCount() { return listFile.length; } @Override public Object getItem(int arg0) { return arg0; } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(final int postion, View arg1, ViewGroup arg2) { View views = LayoutInflater.from(MainActivity.this).inflate( R.layout.list_item, null); LinearLayout parent = (LinearLayout) views.findViewById(R.id.list_parent); TextView filename = (TextView) views.findViewById(R.id.show_file_name); Button plays = (Button) views.findViewById(R.id.bt_list_play); Button stop = (Button) views.findViewById(R.id.bt_list_stop); //在textview中顯示的時候把“.amr”去掉 filename.setText(listFile[postion].substring(0, listFile[postion].length() - 4)); parent.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { AlertDialog aler = new AlertDialog.Builder(MainActivity.this) .setTitle("確定刪除該錄音?") .setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog , int which) { File file = new File(path + "/" + listFile[postion]); file.delete(); // 在刪除文件後刷新文件名列表 File files = new File(path); listFile = files.list(); // 當文件被刪除刷新ListView showRecord.notifyDataSetChanged(); } }) .setNegativeButton("取消", null) .create(); //設置不允許點擊提示框之外的區域 aler.setCanceledOnTouchOutside(false); aler.show(); return false; } }); // 播放錄音 plays.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { //確認不是在錄音的過程中播放 if (myRecorder == null) { try { myPlayer.reset(); myPlayer.setDataSource(path + "/" + listFile[postion]); if (!myPlayer.isPlaying()) { myPlayer.prepare(); myPlayer.start(); } else { myPlayer.pause(); } } catch (IOException e) { e.printStackTrace(); } } else { Toast.makeText(MainActivity.this, "請不要再錄音的過程中播放!", Toast.LENGTH_SHORT).show(); } } }); // 停止播放 stop.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (myRecorder == null && myPlayer.isPlaying()) { myPlayer.stop(); } } }); return views; } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start: final EditText filename = new EditText(this); AlertDialog aler = new Builder(this) .setTitle("請輸入要保存的文件名") .setView(filename) .setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String text = filename.getText().toString(); //如果文件名為空則跳出提示信息 if (text.equals("")) { Toast.makeText(MainActivity.this, "請不要輸入空的文件名!", Toast.LENGTH_SHORT).show(); } else { //開啟錄音 RecorderStart(text); start.setText("正在錄音中。。"); start.setEnabled(false); stop.setEnabled(true); // 在增添文件後刷新文件名列表 File files = new File(path); listFile = files.list(); // 當文件增加刷新ListView showRecord.notifyDataSetChanged(); } } }) .setNegativeButton("取消",null) .create(); //設置不允許點擊提示框之外的區域 aler.setCanceledOnTouchOutside(false); aler.show(); break; case R.id.stop: myRecorder.stop(); myRecorder.release(); myRecorder = null; // 判斷是否保存 如果不保存則刪除 aler = new AlertDialog.Builder(this) .setTitle("是否保存該錄音") .setPositiveButton("確定", null) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { saveFilePath.delete(); // 在刪除文件後刷新文件名列表 File files = new File(path); listFile = files.list(); // 當文件被刪除刷新ListView showRecord.notifyDataSetChanged(); } }).create(); //設置不允許點擊提示框之外的區域 aler.setCanceledOnTouchOutside(false); aler.show(); start.setText("錄音"); start.setEnabled(true); stop.setEnabled(false); default: break; } } private void RecorderStart(String text) { try { myRecorder = new MediaRecorder(); // 從麥克風源進行錄音 myRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); // 設置輸出格式 myRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // 設置編碼格式 myRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); String paths = path + "/" + text + ".amr"; saveFilePath = new File(paths); myRecorder.setOutputFile(saveFilePath.getAbsolutePath()); myRecorder.prepare(); // 開始錄音 myRecorder.start(); } catch (Exception e) { e.printStackTrace(); } } @Override protected void onDestroy() { super.onDestroy(); // 如果myPlayer正在播放,那麼就停止播放,並且釋放資源 if (myPlayer.isPlaying()) { myPlayer.stop(); myPlayer.release(); } //如果myRecorder有內容(代表正在錄音),那麼就直接釋放資源 if(myRecorder!=null) { myRecorder.release(); myPlayer.release(); } } }
activity_main:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#000" android:padding="13dp" android:text="語音筆" android:textColor="#fff" android:textSize="22sp" android:text /> <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:padding="10dp" ></ListView> <LinearLayout android:id="@+id/li1" android:padding="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/start" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="20sp" android:text="開始錄音" /> <Button android:id="@+id/stop" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:enabled="false" android:textSize="20sp" android:text="停止錄音" /> </LinearLayout> </LinearLayout>
list_item:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" android:id="@+id/list_parent" android:orientation="horizontal"> <TextView android:id="@+id/show_file_name" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="文件名" android:textColor="#000" android:textSize="20sp" /> <Button android:id="@+id/bt_list_play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:text="播放" /> <Button android:id="@+id/bt_list_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:text="停止" /> </LinearLayout>
以上就是本文的全部內容,希望對大家實現Android軟件編程有所幫助。
Android WebView常見問題解決方案匯總:就目前而言,如何應對版本的頻繁更新呢,又如何靈活多變地展示我們的界面呢,這又涉及到了web app與native ap
開源項目效果調用實例必練基本功Android studio 項目導入依賴compile路徑dependencies{ compile 'com.androi
我們在創建AVD時,在命令行窗口中輸入android list targets會提示:android不是內部或外部命令,如圖1,其實這主要是由於
這篇文章有一半是copy別人的,站在巨人的肩膀上,我們才能看得更高更遠......在開始討論android的消息處理機制前,先來談談一些基本相關的術語。通信的同步(Syn