【教えてください】ボイスレコーダーのアプリ

977 views
Skip to first unread message

karukaru

unread,
Oct 1, 2012, 1:21:05 AM10/1/12
to android-g...@googlegroups.com
ボイスレコーダーを作ろうと思い下記のようなプログラムを書きました。
しかし、実行してみると、ボタン「Recording」は表示されるのですが、タップしても何も起きません。なぜでしょうか?
 
 
--------------Rokuon_shimasuyo.java----------------------------
package com.example.mediarecorder;
 
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.View;

public class Rokuon_shimasuyo extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rokuon_shimasuyo);
    }
    MediaRecorder recorder;
   
    public void onClick(View v){
     
     switch(v.getId()){
     
     case R.id.Start:
      
      recorder = new MediaRecorder();
      recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
      recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
      recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
      
      String filePath = Environment.getExternalStorageDirectory() + "/audio.3gp";
      recorder.setOutputFile(filePath);
      
      try {           
       recorder.prepare();
       } catch (Exception e) {
        e.printStackTrace();
        }
       recorder.start();   //録音開始
       break;
       case R.id.Stop:        //ストップボタン押下
        recorder.stop();
        recorder.reset();   //オブジェクトのリセット
        //release()前であればsetAudioSourceメソッドを呼び出すことで再利用可能
        recorder.release(); //Recorderオブジェクトの解放
        break;
       }

     }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_rokuon_shimasuyo, menu);
        return true;
    }
}
 
---------activity_rokuon_shimasuyo.xml-----------
<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" >

 <Button android:text="RECORDING"
      android:id="@+id/Start"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"></Button>
 <Button android:text="STOP"
      android:id="@+id/Stop"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"></Button>
</LinearLayout>

karukaru

unread,
Oct 4, 2012, 1:36:55 AM10/4/12
to android-g...@googlegroups.com
 
あきたさんありがとうございます。
教えていただいたサイトを参考に、下記のプログラムを作成しました。
しかし、今度は「Start」ボタンをタップすると、エラーが表示されて強制終了するようになりました。
なぜでしょうか。
 
package com.example.voice;
import android.app.Activity;

import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.widget.LinearLayout;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.View.OnClickListener;
public class Voice extends Activity implements OnClickListener{
    private final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;
    private Button Start;
    private Button Stop;
    @Override protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.HORIZONTAL);
        setContentView(linearLayout);
        Start = new Button(this);
        Start.setText("Start");
        Start.setOnClickListener(this);
        linearLayout.addView(Start,
          new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
        Stop = new Button(this);
        Stop.setText("Stop");
        Stop.setOnClickListener(this);
        linearLayout.addView(Stop,
          new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
    }
    MediaRecorder recorder;
    public void onClick(View v) {
        if (v == Start){

      recorder = new MediaRecorder();
      recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
      recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
      recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
      
      String filePath = Environment.getExternalStorageDirectory() + "/audio.3gp";
      recorder.setOutputFile(filePath);
      
      try {           
       recorder.prepare();
       } catch (Exception e) {
        e.printStackTrace();
        }
       recorder.start();
        }else if (v == Stop){

   recorder.stop();
   recorder.reset();   //オブジェクトのリセット
   //release()前であればsetAudioSourceメソッドを呼び出すことで再利用可能
   recorder.release(); //Recorderオブジェクトの解放
        }
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_voice, menu);
        return true;
    }
}
 
logにはこのように表示されていました。
10-04 14:32:14.202: W/dalvikvm(1021): threadid=1: thread exiting with uncaught exception (group=0x2aac87d8)
10-04 14:32:14.212: E/AndroidRuntime(1021): FATAL EXCEPTION: main
10-04 14:32:14.212: E/AndroidRuntime(1021): java.lang.RuntimeException: setAudioSource failed.
10-04 14:32:14.212: E/AndroidRuntime(1021):  at android.media.MediaRecorder.setAudioSource(Native Method)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at com.example.voice.Voice.onClick(Voice.java:45)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at android.view.View.performClick(View.java:2420)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at android.view.View$PerformClick.run(View.java:8840)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at android.os.Handler.handleCallback(Handler.java:587)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at android.os.Handler.dispatchMessage(Handler.java:92)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at android.os.Looper.loop(Looper.java:123)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at android.app.ActivityThread.main(ActivityThread.java:4627)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at java.lang.reflect.Method.invokeNative(Native Method)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at java.lang.reflect.Method.invoke(Method.java:521)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
10-04 14:32:14.212: E/AndroidRuntime(1021):  at dalvik.system.NativeStart.main(Native Method)
setAudioSource failed.ということは、マイクが見つからないということでしょうか?
私が使っている端末にはちゃんとマイクが付いているはずなのですが、、、
端末はDocomo Regza T-01Cを使用しています。

scarviz

unread,
Oct 4, 2012, 3:23:56 AM10/4/12
to android-g...@googlegroups.com

こんにちは。
scarvizです。

ちょうどボイスレコーダー作ろっかなとか思ってたので、
興味があるので僕も少し見てみました。

ログで、45行目でエラー出てるとあるので、
おそらく
recorder.setOutputFile(filePath);
の部分ではないかなと思います。
なので、setAudioSource failed.というのは、
マイクがないという意味ではなく、
オーディオファイルがないという意味だと思います。

ファイルパスに指定しているファイルは存在しますでしょうか?
もし無いなら、ファイルの存在チェックをして、
ない場合は新規作成するようにしたら良いんじゃないかなと思います。

試してないんで憶測ですいませんが、
頑張ってください!

2012/10/04 14:37 "karukaru" <kotan...@gmail.com>:
--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このディスカッションをウェブ上で閲覧するには、https://groups.google.com/d/msg/android-group-japan/-/UK442vbaJS0J にアクセスしてください。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してください。
詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセスしてください。

あき

unread,
Oct 4, 2012, 4:31:11 AM10/4/12
to android-g...@googlegroups.com
あきたです。

# なんか気になったので仕事中なのに確認してしまった。Let's 残業!

当方、レコーダーは使ったことがないので細かいことは分かりませんが、
さしあたり録音できる状態になったコードを用意しましたので提示します。
ところどころコメントを入れてありますので、ご確認下さい。


--- Voice.java -------------------------------------------------

package com.example.voice;

import android.app.Activity;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;


public class Voice extends Activity implements OnClickListener {

// わざわざ変な定数を定義せず、そのまま使う。
//    private final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;

// 変数名の先頭は大文字でなく小文字。Start だと、大半の Java プログラマは「Startというクラス」だと思ってしまいます。
//    private Button Start;
    private Button start;
//    private Button Stop;
    private Button stop;

// 特に意図がなければ可視性は private にしておくのが吉。
//    MediaRecorder recorder;
    private MediaRecorder recorder;


    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.HORIZONTAL);
        setContentView(linearLayout);
        start = new Button(this);
        start.setText("Start");
        start.setOnClickListener(this);
        linearLayout.addView(start, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        stop = new Button(this);
        stop.setText("Stop");
        stop.setOnClickListener(this);
        linearLayout.addView(stop, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
    }

    public void onClick(View v) {
        try {
            if (v == start) {
                // このあたりは
                // http://developer.android.com/intl/ja/reference/android/media/MediaRecorder.html#setAudioSource%28int%29
                // の「A common case of using MediaRecorder to record audio works as follows: 」あたりを丸々参考にしました
                recorder = new MediaRecorder();
                recorder.setAudioSource(MediaRecorder.AudioSource.MIC);    // パーミッション定義が必要になるようです
                recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    // DEFAULT との差がなんなのかは未調査です
                String filePath = Environment.getExternalStorageDirectory()
                        + "/audio.3gp";    // SDカードに書くため、パーミッション定義が必要になります
                recorder.setOutputFile(filePath);
                recorder.prepare();
                recorder.start(); // Recording is now started

                Toast.makeText(this, "START!!", Toast.LENGTH_LONG).show();    // とってるのかよくわからないので、開始したことを表示

            } else if (v == stop) {

                recorder.stop();
                recorder.reset(); // オブジェクトのリセット
                // release()前であればsetAudioSourceメソッドを呼び出すことで再利用可能
                recorder.release(); // Recorderオブジェクトの解放

                Toast.makeText(this, "STOP!!", Toast.LENGTH_LONG).show();    // とってるのかよくわからないので、終了したことを表示

            }

        } catch (Exception e) {
            Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
            Log.e("Voicd", e.toString(), e);
        }
    }

    // メニューの処理は割愛

}
----------------------------------------------------------------

--- AndroidManifest.xml ----------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.voice"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".Voice" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>
----------------------------------------------------------------


なお、karukaru さんに一点謝らねばならないことが。
先に提示したサイトをそのまま適用されてしまうとは思わず、失礼いたしました。

スレッド1番目で提示してもらったレイアウトXML を生かしたかたちで
リスナを実装することができます。

こちらはブラウザ上で書いているので動作未確認ですが、ご参考までに:

----------------------------------------------------------------
public class Rokuon_shimasuyo extends Activity implements OnClickListener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rokuon_shimasuyo);
        Button startButton = (Button) this.findViewById(R.id.Start);
        startButton.setOnClickListener(this);
        // End ボタンも同じように
    }
----------------------------------------------------------------


もう少しで録音できると思いますので、がんばってください。
# あと、冒頭で名乗っていただけると嬉しいです。

--
あきた

scarviz

unread,
Oct 4, 2012, 6:49:20 AM10/4/12
to android-g...@googlegroups.com

こんばんは。
scarvizです。

すいません。
全然検討違いでした。

僕が前にサンプルで作ったソースコード確認したら、
同じこと書いていたので、ファイル無かったら自動で作られますね。
いい加減な事言って、申し訳ないです。

あきたさんが書かれてる通り、パーミッションの設定ができていないためと思います。

あきたさんがソースコード載せてくれたので、
不要と思いますが、僕の方で動作確認しているものを下記に置いています。
「 RecorderSample 」がそれになります。
http://code.google.com/p/scarviz-project/source/browse/#svn%2Ftrunk%2FRecorderSample%253Fstate%253Dclosed

レイアウトはxmlに分離しているので、
分けたい場合は良かったら参考にしてください。
内容はあきたさんのとほとんど同じものです。

2012/10/04 17:31 "あき" <akit...@gmail.com>:
--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このディスカッションをウェブ上で閲覧するには、https://groups.google.com/d/msg/android-group-japan/-/ju7mr6d5MHsJ にアクセスしてください。

karukaru

unread,
Oct 14, 2012, 1:06:22 PM10/14/12
to android-g...@googlegroups.com
失礼しました。
遅れましたが、karukaruと申します。
 
あきたさん、scarvizさんありがとうございます。
ご教授して頂いた通りにプログラムを組みなおすことで無事アプリを作ることができました。
今度は、保存したファイルを再生、編集するアプリの制作にチャレンジしてみようとおもいます。
また、機会がありましたらご教授おねがいします。
Reply all
Reply to author
Forward
0 new messages