質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

1315閲覧

クラス間での配列データの移動の仕方がわからない

yasiko

総合スコア6

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2021/09/30 09:01

メインのアクティビティでAudioRecodoを用いてマイクから一定間隔で音声データ(配列のデータ)を取得して、
それをサーフェスビューで波形を描画して視覚的に音声データを確認したいのですが、
クラス間での配列データの受け渡し?移動?の仕方がわかりません。詳しい方教えてください。

↓MainPage メインのアクティビティ

java

1import android.Manifest; 2import android.app.Activity; 3import android.content.Intent; 4import android.content.pm.PackageManager; 5import android.database.sqlite.SQLiteDatabase; 6import android.media.AudioFormat; 7import android.media.AudioRecord; 8import android.media.MediaRecorder; 9import android.os.Bundle; 10import android.os.Handler; 11import android.util.Log; 12import android.view.Window; 13 14import androidx.core.app.ActivityCompat; 15import androidx.core.content.ContextCompat; 16 17public class MainPage extends Activity 18{ 19 public boolean loop = true;//loop用 20 public Thread thread; 21 public int co=0;//loop用のカウント 22 23 private int PERMISSIONS_REQUEST_RECORD_AUDIO = 99; 24 25 // オーディオレコード定数 26 public AudioRecord record; 27 28 public int count=0; 29 30 public static final int AUDIO_SAMPLE_FREQ = 44100;//サンプリング周波数 31 32 public static final int AUDIO_BUFFER_SIZE = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_FREQ, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); //オーディオレコード用バッファのサイズ 33 34 public static final int FRAME_BUFFER_SIZE = AUDIO_BUFFER_SIZE / 2; 35 36 public short data[] = new short[FRAME_BUFFER_SIZE]; 37 38 public short test[] = new short[32];//配列テスト 39 40 public void onCreate(Bundle bundle) 41 { 42 super.onCreate(bundle); 43 requestWindowFeature(Window.FEATURE_NO_TITLE); 44 45 for(int i=0; i<32; i++) //格納 46 { 47 test[i]= (short) i; 48 } 49 50 Log.d("MainPage", "onCreate起動時"); 51 52 for(int i=0; i<32; i++) // test 53 { 54 Log.d("MainPage", "" + test[i]);//配列logcat表示 55 } 56 57 setContentView(new MySurfaceView(this));//サーフェスビュー 58 59 60 thread = new Thread(new Runnable()//ループ 61 { 62 private Handler handler = new Handler(getMainLooper()); 63 64 @Override 65 public void run() 66 { 67 record = new AudioRecord(MediaRecorder.AudioSource.MIC, 68 AUDIO_SAMPLE_FREQ, AudioFormat.CHANNEL_IN_MONO, 69 AudioFormat.ENCODING_PCM_16BIT, AUDIO_BUFFER_SIZE); 70 71 // マルチスレッドにしたい処理 ここから 72 while(loop) 73 { 74 try 75 { 76 co++; 77 78 thread.sleep(5000); 79 80 handler.post(new Runnable() 81 { 82 @Override 83 public void run() 84 { 85 Log.d("MainPage", "ループNo." + co); 86 // 録音開始 87 record.startRecording(); 88 89 record.read(data, 0, FRAME_BUFFER_SIZE); 90 91 for(int i=0; i<FRAME_BUFFER_SIZE; i++) 92 { 93 Log.d("MainPage", "data["+ i +"] = " + data[i]);//音声データ配列 logcat表示 94 } 95 96 97 } 98 }); 99 100 } 101 catch (InterruptedException e) 102 { 103 } 104 105 }//while末 106 107 // マルチスレッドにしたい処理 ここまで 108 109 }//Run末 110 111 });//thread末 112 113 114 115 int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO); 116 117 if (permissionCheck == PackageManager.PERMISSION_GRANTED) // すでにユーザーがパーミッションを許可 118 { 119 thread.start(); 120 } 121 else // ユーザーはパーミッションを許可していない 122 { 123 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO); 124 } 125 126 127 }//onCreate末 128 129 @Override 130 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 131 { 132 if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) 133 { 134 if (grantResults[0] != android.content.pm.PackageManager.PERMISSION_GRANTED) // ユーザが許可しなかったらアプリを終了する 135 { 136 finish(); 137 } 138 else 139 { 140 thread.start(); 141 } 142 } 143 } 144 145}//MainPage末

↓MySurfaceView 波形描画用のサーフェスビュー

java

1import android.content.Context; 2import android.content.Intent; 3import android.graphics.Canvas; 4import android.graphics.Color; 5import android.graphics.Paint; 6import android.graphics.Path; 7import android.view.SurfaceHolder; 8import android.view.SurfaceView; 9 10import java.util.Calendar; 11import java.util.Random; 12 13public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable 14{ 15 private Thread thread; 16 private SurfaceHolder holder; 17 18 public int count = 0; 19 20 private float screenWidth, screenHeight; 21 22 23 public short frn[] = new short[32];//配列 24 25 public MySurfaceView(Context context) 26 { 27 super(context); 28 holder = getHolder(); 29 holder.addCallback(this); 30 holder.setFixedSize(getWidth(), getHeight()); 31 } 32 33 @Override 34 public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) 35 { 36 screenWidth = w; 37 screenHeight = h; 38 39 thread = new Thread(this); 40 thread.start(); 41 } 42 43 @Override 44 public void surfaceCreated(SurfaceHolder holder) 45 { 46 } 47 48 @Override 49 public void surfaceDestroyed(SurfaceHolder holder) 50 { 51 } 52 53 @Override 54 public void run() 55 { 56 while (thread != null) 57 { 58 long nextTime = System.currentTimeMillis()+250;//250msec 59 try 60 { 61 Thread.sleep(nextTime - System.currentTimeMillis()); 62 } 63 catch (Exception e) 64 { 65 } 66 67 68 for (int i=0; i<32; i++)//とりあえずは乱数を入れてそれっぽく ここに音声データを置き換えたい 69 { 70 Random r = new Random(); // https://kazukii777.blogspot.com/2013/05/android_6460.html 乱数生成 71 frn[i] = (short) r.nextInt(255); 72 } 73 74 doDraw(holder); 75 } 76 } 77 78 private void doDraw(SurfaceHolder holder) 79 { 80 81 Canvas canvas = holder.lockCanvas(); 82 83 if (canvas != null) 84 { 85 count++; 86 87 Paint paint = new Paint(); 88 paint.setAntiAlias(true); 89 canvas.drawColor(Color.BLACK); 90 91 92 paint.setStrokeWidth(2);//線幅 93 paint.setStyle(Paint.Style.STROKE); 94 paint.setColor(Color.RED); 95 Path path =new Path(); 96 for (int i=0; i<32; i++) 97 { 98 if (i==0) 99 { 100 path.moveTo((screenWidth/32)*i,screenHeight/2 +frn[i]);//開始座標 101 } 102 else 103 { 104 path.lineTo((screenWidth/32)*i,screenHeight/2 + frn[i]); 105 } 106 107 } 108 canvas.drawPath(path,paint); 109 110 111 112 paint.setAntiAlias(true); 113 paint.setTextSize(120); 114 paint.setColor(Color.WHITE); 115 canvas.drawText("Surface_View_Count",0,400,paint); 116 117 paint.setAntiAlias(true); 118 paint.setTextSize(120); 119 paint.setColor(Color.WHITE); 120 canvas.drawText("-"+count+"-",0,600,paint); 121 122 123 124 holder.unlockCanvasAndPost(canvas); 125 } 126 } 127}

とりあえずは乱数で波形を動かしているのですが、これを音声データに置き換えたいです。

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

クラス間での配列データの受け渡し?移動?の仕方

のみに関しましては、 MySurfaceView に frn 配列へのセッターメソッドを作り、 MainPage で録音後に MySurfaceView インスタンスに対してそのセッターを呼ぶだけに思います。
ですが、双方とも別スレッドで動作していますので、使用・更新のタイミングを意識しておかないと、表示が乱れる等の現象が発生するかもしれません。


オシロスコープのように動くモノが出来ましたので公開させていただきます。

MainActivity.java

java

1package com.teratail.q362100; 2 3import androidx.activity.result.ActivityResultLauncher; 4import androidx.activity.result.contract.ActivityResultContracts; 5import androidx.appcompat.app.*; 6import androidx.core.content.ContextCompat; 7import androidx.fragment.app.DialogFragment; 8 9import android.Manifest; 10import android.app.Dialog; 11import android.content.pm.PackageManager; 12import android.media.*; 13import android.os.*; 14import android.view.Gravity; 15import android.widget.*; 16 17public class MainActivity extends AppCompatActivity { 18 @SuppressWarnings("UnusedDeclaration") 19 private static final String TAG = "MainActivity"; 20 21 private static final int AUDIO_SAMPLE_FREQ = 44100;//サンプリング周波数 22 private static final int FRAME_RATE = 10; 23 private static final String START_TEXT = "START"; 24 private static final String STOP_TEXT = "STOP"; 25 26 private SurfaceDrawer surfaceDrawer; 27 private Button button; 28 private HandlerThread listenerThread; 29 private AudioRecord recorder; 30 31 public void onCreate(Bundle bundle) { 32 super.onCreate(bundle); 33 setContentView(R.layout.activity_main); 34 setTitle("AudioRecord"); 35 36 surfaceDrawer = new SurfaceDrawer(findViewById(R.id.surfaceView)); 37 38 button = findViewById(R.id.button); 39 button.setEnabled(true); 40 button.setText(START_TEXT); 41 button.setOnClickListener(v -> { 42 switch(button.getText().toString()) { //トグル 43 case START_TEXT: 44 permissionCheckAndStart(); 45 break; 46 case STOP_TEXT: 47 recorder.stop(); 48 button.setText(START_TEXT); 49 break; 50 } 51 }); 52 } 53 54 //権限要求ダイアログ表示・返答受付 55 private final ActivityResultLauncher<String> requestPermissionLauncher = 56 registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { 57 if (isGranted) { 58 start(); 59 } else { 60 Toast t = Toast.makeText(this, "権限が許可されなかった為、実行できません。", Toast.LENGTH_LONG); 61 t.setGravity(Gravity.CENTER, 0, 0); 62 t.show(); 63 } 64 }); 65 66 //権限説明ダイアログ ok 押下 → 権限要求ダイアログ 67 public static class ExplainDialogFragment extends DialogFragment { 68 @Override 69 public Dialog onCreateDialog(Bundle savedInstanceState) { 70 MainActivity activity = (MainActivity)requireActivity(); 71 return new AlertDialog.Builder(activity) 72 .setTitle("使用許可の説明") 73 .setMessage("音声波形を表示するにはマイクの使用(「音声の録音」)の許可が必要です") 74 .setNeutralButton(android.R.string.cancel, (dialog,which)->{}) 75 .setPositiveButton(android.R.string.ok, (dialog,which)->{ 76 activity.requestPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO); 77 }) 78 .create(); 79 } 80 } 81 82 //権限チェック 83 private void permissionCheckAndStart() { 84 if(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) { 85 start(); 86 } else if (shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)) { 87 new ExplainDialogFragment().show(getSupportFragmentManager(), "Explain"); 88 } else { 89 requestPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO); 90 } 91 } 92 93 //波形表示開始 94 private void start() { 95 if(recorder == null) initialize(); 96 recorder.startRecording(); 97 button.setText(STOP_TEXT); 98 } 99 100 private void initialize() { 101 int frameBufferSize = AUDIO_SAMPLE_FREQ / FRAME_RATE; 102 short[] audioData = new short[frameBufferSize]; 103 104 recorder = settingRecorder(AUDIO_SAMPLE_FREQ, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, frameBufferSize); 105 106 listenerThread = new HandlerThread("RecordPositionUpdateListenerThread"); 107 listenerThread.start(); 108 109 recorder.setRecordPositionUpdateListener(new AudioRecord.OnRecordPositionUpdateListener() { 110 @Override 111 public void onMarkerReached(AudioRecord recorder) {} 112 113 @Override 114 public void onPeriodicNotification(AudioRecord recorder) { 115 recorder.read(audioData, 0, audioData.length); 116 surfaceDrawer.draw(audioData); 117 } 118 }, new Handler(listenerThread.getLooper())); //HandlerThread でリスナを実行 119 } 120 121 private void terminate() { 122 if(recorder != null) { 123 recorder.stop(); 124 recorder.release(); 125 } 126 recorder = null; 127 128 if(listenerThread != null) listenerThread.quit(); 129 listenerThread = null; 130 } 131 132 private AudioRecord settingRecorder(int sampleRateInHz, int channelConfig, int audioFormat, int frameBufferSize) { 133 int minBufferSize = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); 134 if(minBufferSize == AudioRecord.ERROR_BAD_VALUE) throw new IllegalArgumentException(); 135 if(minBufferSize == AudioRecord.ERROR) throw new IllegalStateException("minBufferSize"); 136 137 int bufferSizeInBytes = Math.max(minBufferSize, frameBufferSize*10); //"*10"は余裕分 138 139 AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes); 140 if(recorder.getState() != AudioRecord.STATE_INITIALIZED) throw new IllegalStateException("recorder.getState"); 141 142 if(recorder.setPositionNotificationPeriod(frameBufferSize) != AudioRecord.SUCCESS) throw new IllegalStateException("setPositionNotificationPeriod frameBufferSize="+frameBufferSize); 143 144 return recorder; 145 } 146 147 @Override 148 protected void onPause() { //停止 149 super.onPause(); 150 terminate(); 151 } 152 153 @Override 154 protected void onResume() { //再開 155 super.onResume(); 156 if(button.getText().toString().equals(STOP_TEXT)) { //実行中だった 157 permissionCheckAndStart(); 158 } 159 } 160}

レイアウト: activity_main.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<androidx.constraintlayout.widget.ConstraintLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:app="http://schemas.android.com/apk/res-auto" 5 xmlns:tools="http://schemas.android.com/tools" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent" 8 tools:context=".MainActivity"> 9 10 <SurfaceView 11 android:id="@+id/surfaceView" 12 android:layout_width="0dp" 13 android:layout_height="0dp" 14 app:layout_constraintBottom_toTopOf="@id/button" 15 app:layout_constraintLeft_toLeftOf="parent" 16 app:layout_constraintRight_toRightOf="parent" 17 app:layout_constraintTop_toTopOf="parent" /> 18 19 <Button 20 android:id="@+id/button" 21 android:layout_width="0dp" 22 android:layout_height="wrap_content" 23 android:text="START" 24 android:layout_margin="10dp" 25 app:layout_constraintBottom_toBottomOf="parent" 26 app:layout_constraintLeft_toLeftOf="parent" 27 app:layout_constraintRight_toRightOf="parent" /> 28 29</androidx.constraintlayout.widget.ConstraintLayout>

SurfaceDrawer.java

java

1package com.teratail.q362100; 2 3import android.graphics.Canvas; 4import android.graphics.Color; 5import android.graphics.Paint; 6import android.graphics.Path; 7import android.util.Log; 8import android.view.SurfaceHolder; 9import android.view.SurfaceView; 10 11public class SurfaceDrawer implements SurfaceHolder.Callback { 12 @SuppressWarnings("UnusedDeclaration") 13 private static final String TAG = "SurfaceDrawer"; 14 15 private static final float COMPRESSION_RATE = 10f; 16 17 private SurfaceHolder holder; 18 private float canvasWidth, canvasVerticalCenter; 19 private final Paint pathPaint; 20 private final Path path = new Path(); 21 22 public SurfaceDrawer(SurfaceView surfaceView) { 23 holder = surfaceView.getHolder(); 24 holder.addCallback(this); 25 26 pathPaint = new Paint(); 27 pathPaint.setAntiAlias(true); 28 pathPaint.setStrokeWidth(2);//線幅 29 pathPaint.setStyle(Paint.Style.STROKE); 30 pathPaint.setColor(Color.GREEN); 31 } 32 33 @Override 34 public void surfaceCreated(SurfaceHolder holder) { 35 //Log.d(TAG, "surfaceCreated"); 36 Canvas canvas = holder.lockCanvas(); 37 if(canvas == null) return; 38 39 canvas.drawColor(Color.BLACK); 40 holder.unlockCanvasAndPost(canvas); 41 } 42 43 @Override 44 public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) { 45 //Log.d(TAG, "surfaceChanged w="+w+", h="+h); 46 canvasWidth = w; 47 canvasVerticalCenter = h / 2f; 48 } 49 50 @Override 51 public void surfaceDestroyed(SurfaceHolder holder) { 52 //Log.d(TAG, "surfaceDestroyed"); 53 } 54 55 public void draw(short[] data) { 56 if(data == null || data.length < 2) return; 57 58 Canvas canvas = holder.lockCanvas(); 59 if(canvas == null) { 60 Log.d(TAG, "holder.lockCanvas() is null."); 61 return; 62 } 63 64 canvas.drawColor(Color.BLACK); //塗り潰し 65 66 path.rewind(); 67 path.moveTo(0, canvasVerticalCenter + data[0] / COMPRESSION_RATE); 68 for(int x=1; x<canvasWidth; x++) { 69 path.lineTo(x, canvasVerticalCenter + data[(int)(data.length / canvasWidth * x)] / COMPRESSION_RATE); 70 } 71 canvas.drawPath(path, pathPaint); 72 73 holder.unlockCanvasAndPost(canvas); 74 } 75}

app/build.gradle
dependencies に追加

plain

1 implementation 'androidx.activity:activity:1.3.1'

AndroidManifest.xml 追加

xml

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

投稿2021/09/30 11:47

編集2021/10/05 14:21
jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yasiko

2021/10/01 09:21

親身に解答ありがとうございます。 タイミングは後で考えようと思っていました。 "MySurfaceView に frn 配列へのセッターメソッドを作り、 MainPage で録音後に MySurfaceView インスタンスに対してそのセッターを呼ぶ" インスタンスもセッターメソッドも調べたのですがいまいち理解できず、困ってしまいました。 jimbeさんが書いて頂いたプログラムでいうと、 MainActivity の surfaceDrawer.draw(audioData); でデータを送って SurfaceDrawer.java の public void draw(short[] data) {....} で受け取るかんじでしょうか?
yasiko

2021/10/01 09:24

後、jimbeさんが書いて頂いたプログラム実行できずわからずにいます、 import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; がインポート出来ないです。
jimbe

2021/10/01 11:36 編集

AndroidStudio の環境が異なるでしょうか。こちらは ArcticFox 2020.3.1 pache2 です。 古い AndroidStudio だと、プロジェクトが androidx(JetPack) を使わない設定になっているかもしれません。 build.gradle も載せておきますね。(とはいえ、AndroidStudio のバージョンアップに伴って Gradle もアップしていますので、古い Gradle では意味が無いかもしれません。その場合は AndroidStudio のアップデートを強くお勧めします。) 配列の受け渡しにつきましては、まさしくdraw メソッドの部分に当たります。
yasiko

2021/10/04 08:52

AndroidStudio のバージョンアップして、新規プロジェクトの最小SDKをAndroid10にしたら import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; インポートできました。 しかし、実行すると落ちてしまいます。
jimbe

2021/10/04 10:45 編集

バージョンアップお疲れ様です。 コンパイルエラー等は無くなったということでしょうか。 落ちてしまいますか…logcat には何か出ていないでしょうか。 こちらでは、パソコンにマイクが無いので実機(XperiaXZ3/android10 ビルド52.1.C.0.360) でテストしています。 可能であればプロジェクトをどのように作成・実行して落ちたのか、具体的に教えて頂けますか。こちらでも同じ操作をして確認してみますので。
yasiko

2021/10/05 00:51

返信ありがとうございます。 こちらも実機で(Moto G7/android 10)です。 右上の実行押してから少しして、アプリ停止してしまいます。 logcatにはこれが↓表示されます。 I/eratail2021100: Late-enabling -Xcheck:jni I/eratail2021100: Late-enabling -Xcheck:jni E/eratail2021100: Unknown bits set in runtime_flags: 0x8000 E/eratail2021100: Unknown bits set in runtime_flags: 0x8000 I/eratail2021100: Late-enabling -Xcheck:jni E/eratail2021100: Unknown bits set in runtime_flags: 0x8000 W/eratail2021100: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed) W/eratail2021100: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed) E/IAudioFlinger: createRecord returned error -1 E/AudioRecord: createRecord_l(25705): AudioFlinger could not create record track, status: -1 E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1. E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object. D/AndroidRuntime: Shutting down VM --------- beginning of crash E/AndroidRuntime: FATAL EXCEPTION: main Process: net.npaka.teratail20211004, PID: 4324 java.lang.RuntimeException: Unable to start activity ComponentInfo{net.npaka.teratail20211004/net.npaka.teratail20211004.MainActivity}: java.lang.IllegalStateException at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3477) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3620) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2183) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:241) at android.app.ActivityThread.main(ActivityThread.java:7604) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941) Caused by: java.lang.IllegalStateException at net.npaka.teratail20211004.MainActivity.settingRecorder(MainActivity.java:119) at net.npaka.teratail20211004.MainActivity.onCreate(MainActivity.java:40) at android.app.Activity.performCreate(Activity.java:7822) at android.app.Activity.performCreate(Activity.java:7811) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1328) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3452) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3620)  at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2183)  at android.os.Handler.dispatchMessage(Handler.java:107)  at android.os.Looper.loop(Looper.java:241)  at android.app.ActivityThread.main(ActivityThread.java:7604)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
jimbe

2021/10/05 03:02 編集

ログありがとうございます。 > Caused by: java.lang.IllegalStateException > at net.npaka.teratail20211004.MainActivity.settingRecorder(MainActivity.java:119) ということですので、 settingRecorder の中にある 3 つの IllegalStateException のどれかの if 文に引っかかっているようです。 行番号が私のコードと違うのと、手抜きでメッセージを入れなかったので(^^;) どれなのか分かりませんが。 まずどれなのかとパラメータを確認するため、各 IllegalStateException のパラメータを設定したほうが良さそうです。 お手数をお掛けしますが、 1つ目: if(minBufferSize == AudioRecord.ERROR) throw new IllegalStateException("minBufferSize"); 2つ目: if(recorder.getState() != AudioRecord.STATE_INITIALIZED) throw new IllegalStateException("recorder.getState"); 3つ目: if(recorder.setPositionNotificationPeriod(frameBufferSize) != AudioRecord.SUCCESS) throw new IllegalStateException("setPositionNotificationPeriod frameBufferSize="+frameBufferSize); のように、各 IllegalStateException の () 内に追加されたうえで実行・ログを見て頂いて、どの例外が発生しているか教えて頂けますでしょうか。 ちなみに、パッケージ名から察しますと新しくプロジェクトを作られたと思いますが、 AndroidManifest.xml に以下の RECORD_AUDIO のパーミッションは追加されましたでしょうか。 <uses-permission android:name="android.permission.RECORD_AUDIO" /> ※ 回答の settingRecorder を修正し、パーミッションを追加してあるだけですが AndroidManifext.xml も追加しました。
yasiko

2021/10/05 04:39

親身にありがとうございます。orz 1つ目: if(minBufferSize == AudioRecord.ERROR) throw new IllegalStateException("minBufferSize"); 2つ目: if(recorder.getState() != AudioRecord.STATE_INITIALIZED) throw new IllegalStateException("recorder.getState"); 3つ目: if(recorder.setPositionNotificationPeriod(frameBufferSize) != AudioRecord.SUCCESS) throw new IllegalStateException("setPositionNotificationPeriod frameBufferSize="+frameBufferSize); に変えて実行してlogcat見比べたところ↓が変わってました。 java.lang.RuntimeException: Unable to start activity ComponentInfo{net.npaka.teratail20211004/net.npaka.teratail20211004.MainActivity}: java.lang.IllegalStateException: recorder.getState これは2つ目がだめって感じなのでしょうか? マニュフェストありがとうございます。 RECORD_AUDIOはパーミッションを追加してあります。見比べた感じ差異をなさそうです。
jimbe

2021/10/05 05:56

そうですね、AudioRecord の初期化が出来ないようです。 先のログでは beginning of crash の前に数行 AudioRecord に関するものが出ているようなので、それとあわせて調べる必要がありそうですが、すみません今出先なので、戻ってから改めて調べてみます。
jimbe

2021/10/05 09:06

どうも探すとパーミッションの話ばかり出てきますね。 実機の該当アプリの"アプリ情報"から、実際にマイクが許可されているか確認して戴けますか。
yasiko

2021/10/05 09:28

実機にて"アプリ情報"みたところマイク許可されてませんでした。 ここで手動で許可にしたらアプリ動作しました。波形見れました!!すごい
yasiko

2021/10/05 09:31

本来はアプリ起動時に許可するか許可しないかでる?ものなのですか?
jimbe

2021/10/05 09:55

動作して良かったです。 パーミッションチェックのロジックが yasiko さんのコードから入っていますので、そこを通ればインストール直後の初起動時に許可するかのダイアログが出るのですが、私のコードではそのロジックの前にAudioRecord を初期化してしまっているので意味無いですね・・・すみません、私のコードのバグです。 後ほどコードを修正します。
jimbe

2021/10/05 14:33 編集

あれやこれやとやっているうちに行数が増えてしまい 1万文字を超えてしまいまして、 gradle と AndroidManifest を追加分だけにしました。 パーミッション処理やアプリが裏に回った時の動作を直しただけですので、それらが気にならなければ修正して頂かなくても大丈夫です。 えぇと、パーミッションに関しまして、今までアプリ起動時に即チェックする感じでしたが、公式的には "パーミッションが必要な操作をした場合" に行うようにしたいようですので、STARTボタンを押した時にチェックするようにしました。
yasiko

2021/10/06 02:11

新しいコード、ボタン押した時チェック確認できました! 作りたかったアプリはまさにこれで、 これから分からなかったとこは一個一個、紐解いていこうと思います。 親身に色々とありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問