gpt4 book ai didi

java - 下次运行同一应用程序时,线程是否会记住它的状态?

转载 作者:行者123 更新时间:2023-12-01 14:13:09 24 4
gpt4 key购买 nike

我正在尝试将麦克风获得的音频样本传递给扬声器
这是我正在使用的代码,使用 suggestions I obtained here

public class MainActivity extends Activity {
AudioManager am = null;
AudioRecord record =null;
AudioTrack track =null;
final int SAMPLE_FREQUENCY = 44100;
final int SIZE_OF_RECORD_ARRAY = 1024; // 1024 ORIGINAL
final int WAV_SAMPLE_MULTIPLICATION_FACTOR = 1;
int i= 0;
boolean isPlaying = true;
class MyThread extends Thread{
private boolean passThroughMode = true;
/*
@Override
public void run(){
recordAndPlay(passThroughMode);
}
*/

MyThread(){
super();
}

MyThread(boolean newPTV){
this.passThroughMode = newPTV;
}

@Override
public void run(){
short[] lin = new short[SIZE_OF_RECORD_ARRAY];
int num = 0;
// am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
// am.setMode(AudioManager.MODE_IN_COMMUNICATION);
record.startRecording();
track.play();
// while (passThroughMode) {
while (!isInterrupted()) {
num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
for(i=0;i<lin.length;i++)
lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR;
track.write(lin, 0, num);
}
}
/*
public void stopThread(){
passThroughMode = false;
}
*/
}

MyThread newThread;

private void init() {
int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, min);
int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
init();
newThread = new MyThread(true);
newThread.start();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/*
private void recordAndPlay(boolean pTM) {
short[] lin = new short[SIZE_OF_RECORD_ARRAY];
int num = 0;
am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_IN_COMMUNICATION);
record.startRecording();
track.play();
while (pTM) {
num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
for(i=0;i<lin.length;i++)
lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR;
track.write(lin, 0, num);
}
}
*/
public void passStop(View view){
Button playBtn = (Button) findViewById(R.id.playBtn);
// /*
if(!isPlaying){
record.startRecording();
track.play();
isPlaying = true;
playBtn.setText("Pause");
}
else{
record.stop();
track.pause();
isPlaying=false;
playBtn.setText("Pass through");
}
// */
}

/*
@SuppressWarnings("deprecation")
@Override
public void onDestroy(){
newThread.stop();
}
*/

@Override
protected void onDestroy() {
super.onDestroy();
// android.os.Process.killProcess(android.os.Process.myPid());
// killProcess(android.os.Process.myPid());
// newThread.stopThread();
newThread.interrupt();
}
}

在第一次运行期间,程序运行良好,麦克风的声音传递到扬声器,当我按下返回按钮时,线程似乎也停止了,因此当应用程序退出时,传递停止。但是,如果我再次运行该应用程序,则不会发生传递。是否

newThread = new MyThread(true);
newThread.start();

每次执行应用程序时(即调用 onCreate() )启动一个新线程,或者是否由于某种原因记住旧线程的状态?我怎样才能完全重置这个应用程序,以便每次执行时都会启动一个全新的应用程序?

--- 编辑 ---

无中断的替代版本:

public class MainActivity extends Activity {
AudioManager am = null;
AudioRecord record =null;
AudioTrack track =null;
final int SAMPLE_FREQUENCY = 44100;
final int SIZE_OF_RECORD_ARRAY = 1024; // 1024 ORIGINAL
final int WAV_SAMPLE_MULTIPLICATION_FACTOR = 1;
int i= 0;
boolean isPlaying = true;
class MyThread extends Thread{
private volatile boolean passThroughMode = true;
/*
@Override
public void run(){
recordAndPlay(passThroughMode);
}
// */


// /*
MyThread(){
super();
}

MyThread(boolean newPTV){
this.passThroughMode = newPTV;
}
// */

// /*
@Override
public void run(){
short[] lin = new short[SIZE_OF_RECORD_ARRAY];
int num = 0;
// am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
// am.setMode(AudioManager.MODE_IN_COMMUNICATION);
record.startRecording();
track.play();
while (passThroughMode) {
// while (!isInterrupted()) {
num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
for(i=0;i<lin.length;i++)
lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR;
track.write(lin, 0, num);
}
record.stop();
track.stop();
record.release();
track.release();
}
// */

// /*
public void stopThread(){
passThroughMode = false;
}
// */
}

MyThread newThread;

private void init() {
int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, min);
int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
init();
Log.d("MYLOG", "onCreate() called");

//Toast.makeText(getApplicationContext(), "HERE", Toast.LENGTH_SHORT).show();
// newThread = new MyThread(true); // -> Moved this to onResume();
// newThread = new MyThread();
// newThread.start(); // -> Moved this to onResume()
// newThread.run();
}

@Override
protected void onResume(){
super.onResume();
// newThread.stopThread();
Log.d("MYLOG", "onResume() called");
newThread = new MyThread(true);
newThread.start();
}

@Override
protected void onPause(){
super.onPause();
Log.d("MYLOG", "onPause() called");
newThread.stopThread();
// android.os.Process.killProcess(android.os.Process.myPid());
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

/*
private void recordAndPlay(boolean pTM) {
short[] lin = new short[SIZE_OF_RECORD_ARRAY];
int num = 0;
am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_IN_COMMUNICATION);
record.startRecording();
track.play();
while (pTM) {
num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
for(i=0;i<lin.length;i++)
lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR;
track.write(lin, 0, num);
}
}
// */
public void passStop(View view){
Button playBtn = (Button) findViewById(R.id.playBtn);
// /*
if(!isPlaying){
record.startRecording();
track.play();
isPlaying = true;
playBtn.setText("Pause");
}
else{
record.stop();
track.pause();
isPlaying=false;
playBtn.setText("Pass through");
}
// */
}

/*
@SuppressWarnings("deprecation")
@Override
public void onDestroy(){
// newThread.stop();
newThread.stopThread();
}
// */

// /*
@Override
protected void onDestroy() {
super.onDestroy();
newThread.stopThread();
// android.os.Process.killProcess(android.os.Process.myPid());
// killProcess(android.os.Process.myPid());
// newThread.interrupt();
Log.d("MYLOG", "onDestroy() called");
}
// */
}

---编辑2---

08-20 20:57:58.266: D/MYLOG(21936): onResume() called
08-20 20:57:58.266: W/dalvikvm(21936): threadid=11: thread exiting with uncaught exception (group=0x416f5700)
08-20 20:57:58.266: E/AndroidRuntime(21936): FATAL EXCEPTION: Thread-897
08-20 20:57:58.266: E/AndroidRuntime(21936): java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
08-20 20:57:58.266: E/AndroidRuntime(21936): at android.media.AudioRecord.startRecording(AudioRecord.java:517)
08-20 20:57:58.266: E/AndroidRuntime(21936): at com.example.mypassthrough.MainActivity$MyThread.run(MainActivity.java:54)
08-20 20:57:58.286: D/MYLOG(21936): onPause() called
08-20 20:57:58.366: D/MYLOG(21936): onDestroy() called

最佳答案

不,Activity 实例之间的 Thread 对象没有状态持久性。 但是,您错误地假设每次运行应用程序时都会获得一个新的 Activity。 Activity 将持续存在,直到 Android 操作系统决定删除它们。只有当您再次进入应用程序时,才会创建一个新实例 - 否则,您将获得与之前相同的 Activity,并且在这种情况下不会再次调用 onCreate()

换句话说,您应该使用 onResume()onPause() 来进行 init/deinit。请查看lifecycle page了解更多详情。

编辑:另一个问题是您使用interrupt()来控制线程的流程。这并不总是一个好主意,因为 interrupt()several side effects and may not even set the interrupt status to true depending on what's going with the thread 。您应该使用“shouldStop”字段来代替,因为那时语义是由您设置的。

请注意,这个“shouldStop”字段应该是一个字段,将其作为参数传递将不起作用。您应该在 MyThread 中有类似这样的内容:

    @Override
public void run(){
short[] lin = new short[SIZE_OF_RECORD_ARRAY];
int num = 0;
record.startRecording();
track.play();
while (passThroughMode) {
num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
for(i=0;i<lin.length;i++)
lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR;
track.write(lin, 0, num);
}
}

并且,在onPause()中:

@Override
protected void onPause() {
super.onPause();
newThread.stopThread();
}

如果线程仍然没有停止,则表明调用正在阻塞它,这对于 I/O 操作来说是典型的。

编辑2:还有一个问题是你没有stop()release()你的AudioTrack code> 和 AudioRecord 当播放器线程关闭时(在 while 循环之后)。 使用与 I/O 相关的内容时的经验法则是,它通常附加到“ native ”资源,这些资源需要显式“手动”释放(有时还需要分配)。在这些情况下,您应该始终检查类 API 的情况。

编辑 3: ...MyThread 实例以及所有其他资源应该在 完全初始化>onResume(),包括在其中创建新实例,而不是onCreate() 中创建。

关于java - 下次运行同一应用程序时,线程是否会记住它的状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18332297/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com