【问题标题】:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its viewsandroid.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸它的视图
【发布时间】:2019-02-11 22:09:31
【问题描述】:

我的应用是两部安卓手机之间的语音流。

这段代码是监听部分(服务器端)

但我遇到了这个错误

android.view.ViewRootImpl$CalledFromWrongThreadException

我把猫日志放了。看看

请给我你最好的帮助。

提前致谢。

代码:

    package com.example.encryptechatresiving;

import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.view.Menu;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

@SuppressLint("NewApi") public class MainActivity extends Activity {


private Button receiveButton,stopButton;
private TextView recive;
private EditText port;
public static DatagramSocket socket;
private AudioTrack speaker;


private int sampleRate = 44100;      
private int channelConfig =  AudioFormat.CHANNEL_OUT_MONO;    
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;       

private boolean status = true;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    receiveButton = (Button) findViewById (R.id.receive_button);
    stopButton = (Button) findViewById (R.id.stop_button);
    recive= (TextView) findViewById(R.id.receive_label);
    //recive.setText("Created...!");
    receiveButton.setOnClickListener(receiveListener);
    stopButton.setOnClickListener(stopListener);
    //receiveButton.setText("Start Reciving...!");
    //stopButton.setText("Stop Reciving...!");
    port=(EditText) findViewById(R.id.editText1);
    //port.setText("1234");

    AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
    sampleRate =Integer.parseInt( audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
}


private final OnClickListener stopListener = new OnClickListener() {

    @Override
    public void onClick(View v) {
        status = false;
        //recive.setText("Recoder Stop...!");
        speaker.release();
        Log.d("VR","Speaker released");

    }

};


private final OnClickListener receiveListener = new OnClickListener() {

    @Override
    public void onClick(View arg0) {
        status = true;
       // recive.setText(" before Start ");

        startReceiving();

    }

};

public void startReceiving() {

    Thread receiveThread = new Thread (new Runnable() {

        @Override
        public void run() {

            try {

                int port_num=Integer.parseInt(port.getText().toString());

                DatagramSocket socket = new DatagramSocket(port_num);
                Log.d("VR", "Socket Created");


                //minimum buffer size. need to be careful. might cause problems. try setting manually if any problems faced
                int minBufSize =256; //AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
                byte[] buffer = new byte[4096]; //256

                speaker = new AudioTrack(AudioManager.STREAM_VOICE_CALL,sampleRate,channelConfig,audioFormat,16000,AudioTrack.MODE_STREAM);
               //AudioTrack.MODE_STREAM,
                speaker.play();
              // recive.setText("hear anything...?");
                while(status == true) {
                    try {


                        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
                        socket.receive(packet);
                        Log.d("VR", "Packet Received");

                        //reading content from packet
                        buffer=packet.getData();
                        Log.d("VR", "Packet data read into buffer");

                        //sending data to the Audiotrack obj i.e. speaker
                        speaker.write(buffer, 0, minBufSize);
                        Log.d("VR", "Writing buffer content to speaker");

                    } catch(IOException e) {
                        Log.e("VR","IOException");
                    }
                }


            } catch (SocketException e) {
                Log.e("VR", "SocketException");
            }


        }

    });
    receiveThread.start();
}

}

日志:

    05-23 22:56:10.646: D/VR(789): Socket Created
05-23 22:56:10.746: W/dalvikvm(789): threadid=13: thread exiting with uncaught exception (group=0x40a71930)
05-23 22:56:10.807: E/AndroidRuntime(789): FATAL EXCEPTION: Thread-77
05-23 22:56:10.807: E/AndroidRuntime(789): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:823)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.view.View.requestLayout(View.java:15473)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.view.View.requestLayout(View.java:15473)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.view.View.requestLayout(View.java:15473)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.view.View.requestLayout(View.java:15473)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:318)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.view.View.requestLayout(View.java:15473)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.widget.TextView.checkForRelayout(TextView.java:6452)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.widget.TextView.setText(TextView.java:3696)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.widget.TextView.setText(TextView.java:3554)
05-23 22:56:10.807: E/AndroidRuntime(789):  at android.widget.TextView.setText(TextView.java:3529)
05-23 22:56:10.807: E/AndroidRuntime(789):  at com.example.encryptechatresiving.MainActivity$3.run(MainActivity.java:113)
05-23 22:56:10.807: E/AndroidRuntime(789):  at java.lang.Thread.run(Thread.java:856)
05-23 22:56:10.897: W/ActivityManager(291):   Force finishing activity com.example.encryptechatresiving/.MainActivity
05-23 22:56:10.906: W/WindowManager(291): Failure taking screenshot for (246x410) to layer 21010

【问题讨论】:

    标签: android


    【解决方案1】:

    Toast 必须在 UI 线程中。

     Toast.makeText(getApplicationContext(), "Start Talking....",Toast.LENGTH_LONG).show();
    

    【讨论】:

      【解决方案2】:

      其实你是在访问

      port.getText().toString()

      来自单独的非 UI 线程,这是错误的,这就是您收到此异常的原因。所以,尝试从主线程访问它。

      //accessing it from ui-thread
      runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 int port_num=Integer.parseInt(port.getText().toString());
             }
        });
      

      编辑:如果您再次遇到您在 cmets 中提到的 语法错误,请测试编辑后的代码

      private int port_num;
      
      public void startReceiving() {
      
          Thread receiveThread = new Thread (new Runnable() {
      
              @Override
              public void run() {
      
                  try {
      
                      runOnUiThread(new Runnable() {
      
                          @Override
                          public void run() {
                              port_num=Integer.parseInt(port.getText().toString());                           
                          }
                      });
      
      
      
                      DatagramSocket socket = new DatagramSocket(port_num);
                      Log.d("VR", "Socket Created");
      
      
                      //minimum buffer size. need to be careful. might cause problems. try setting manually if any problems faced
                      int minBufSize =256; //AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
                      byte[] buffer = new byte[4096]; //256
      
                      speaker = new AudioTrack(AudioManager.STREAM_VOICE_CALL,sampleRate,channelConfig,audioFormat,16000,AudioTrack.MODE_STREAM);
                     //AudioTrack.MODE_STREAM,
                      speaker.play();
                    // recive.setText("hear anything...?");
                      while(status == true) {
                          try {
      
      
                              DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
                              socket.receive(packet);
                              Log.d("VR", "Packet Received");
      
                              //reading content from packet
                              buffer=packet.getData();
                              Log.d("VR", "Packet data read into buffer");
      
                              //sending data to the Audiotrack obj i.e. speaker
                              speaker.write(buffer, 0, minBufSize);
                              Log.d("VR", "Writing buffer content to speaker");
      
                          } catch(IOException e) {
                              Log.e("VR","IOException");
                          }
                      }
      
      
                  } catch (SocketException e) {
                      Log.e("VR", "SocketException");
                  }
      
      
              }
      
          });
          receiveThread.start();
      }
      

      【讨论】:

      • 你能把所有的源代码都放上来而不是一个部分吗?当我更改它时,我看到另一个错误(不是运行时错误)
      • 语法错误。它说关闭括号。所以我这样做但不工作......!
      • 没有语法错误。但仍然是同一只原木猫。见第一篇文章
      • 如果你把你的整个代码放在runOnUiThread中会怎样?你还是有例外吗?
      • tnx. 通过将整个代码放入 runUiThread.i 来解决问题。我不能给你 +1 为什么。?
      【解决方案3】:

      您不能显示来自背景ThreadToast 消息。所以替换

       Toast.makeText(getApplicationContext(), "Start Talking....",Toast.LENGTH_LONG).show();
      

      new Handler(Looper.getMainLooper()).post(new Runnable() {
             @Override
             public void run() {
                   Toast.makeText(context, "Running background", Toast.LENGTH_SHORT).show();
                  }
              });
      

      这会在 UI Thread 上运行您的 Toast

      【讨论】:

      • 对不起,我犯了一个错误。我放错了源代码。你会再看一遍第一个帖子吗?
      • 你能知道你在哪一行得到了错误。
      • 在 startReceiving 方法中和 Log.d("VR", "Socket Created");
      • 可能是音轨的问题,尝试从 UI Thread 播放音轨。
      • 你认为我可以将整个代码放在 runOnUiThread(new Runnable() {} 方法中吗??
      猜你喜欢
      • 1970-01-01
      • 2013-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      相关资源
      最近更新 更多