Извините, если это неправильный английский, потому что я использую переводчик.
Я скачал программу с github, которая может управлять мышью на телефоне Android. Нет проблем с подключением к серверу, но возникает ошибка при касании текстового поля для управления мышью.
Уникально, что при запуске программы с виртуальным устройством ошибки не возникает и работает хорошо.
Я видел много примеров и ответов, но не могу их решить, поэтому публикую повторно. ;_; Я был бы очень признателен, если бы вы могли сказать мне, какие части изменить.
public class MainActivity extends ActionBarActivity implements View.OnClickListener {
Context context;
Button playPauseButton;
Button nextButton;
Button previousButton;
TextView mousePad;
private boolean isConnected=false;
private boolean mouseMoved=false;
private Socket socket;
private PrintWriter out;
private float initX =0;
private float initY =0;
private float disX =0;
private float disY =0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
playPauseButton = (Button)findViewById(R.id.playPauseButton);
nextButton = (Button)findViewById(R.id.nextButton);
previousButton = (Button)findViewById(R.id.previousButton);
playPauseButton.setOnClickListener(this);
nextButton.setOnClickListener(this);
previousButton.setOnClickListener(this);
mousePad = (TextView)findViewById(R.id.mousePad);
mousePad.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (isConnected && out!=null){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
initX =event.getX();
initY =event.getY();
mouseMoved=false;
break;
case MotionEvent.ACTION_MOVE:
disX = event.getX()- initX;
disY = event.getY()- initY;
initX = event.getX();
initY = event.getY();
if (disX !=0|| disY !=0){
out.println(disX +","+ disY);
}
mouseMoved=true;
break;
case MotionEvent.ACTION_UP:
if (!mouseMoved){
out.println(Constants.MOUSE_LEFT_CLICK);
}
}
}
return true;
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_connect) {
ConnectPhoneTask connectPhoneTask = new ConnectPhoneTask();
connectPhoneTask.execute(Constants.SERVER_IP); //try to connect to server in another thread
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.playPauseButton:
if (isConnected && out!=null) {
out.println(Constants.PLAY);//send "play" to server
}
break;
case R.id.nextButton:
if (isConnected && out!=null) {
out.println(Constants.NEXT); //send "next" to server
}
break;
case R.id.previousButton:
if (isConnected && out!=null) {
out.println(Constants.PREVIOUS); //send "previous"
}
break;
}
}
@Override
public void onDestroy()
{
super.onDestroy();
if (isConnected && out!=null) {
try {
out.println("exit"); //tell server to exit
socket.close(); //close socket
} catch (IOException e) {
Log.e("remotedroid", "Error in closing socket", e);
}
}
}
public class ConnectPhoneTask extends AsyncTask<String,Void,Boolean> {
@Override
protected Boolean doInBackground(String... params) {
boolean result = true;
try {
InetAddress serverAddr = InetAddress.getByName(params[0]);
socket = new Socket(serverAddr, Constants.SERVER_PORT);//Open socket on server IP and port
} catch (IOException e) {
Log.e("remotedroid", "Error while connecting", e);
result = false;
}
return result;
}
@Override
protected void onPostExecute(Boolean result)
{
isConnected = result;
Toast.makeText(context,isConnected?"Connected to server!":"Error while connecting",Toast.LENGTH_LONG).show();
try {
if (isConnected) {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true); //create output stream to send data to server
}
}catch (IOException e){
Log.e("remotedroid", "Error while creating OutWriter", e);
Toast.makeText(context,"Error while connecting",Toast.LENGTH_LONG).show();
}
}
}
}
макет xml:
<TextView
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:layout_above = "@+id/playPauseButton"
android:clickable = "true"
android:background = "@android:color/holo_blue_dark"
android:id = "@+id/mousePad"/>
<Button
android:id = "@+id/playPauseButton"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentBottom = "true"
android:layout_centerHorizontal = "true"
android:text = "Button3" />
<Button
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Left"
android:id = "@+id/previousButton"
android:layout_alignParentBottom = "true"
android:layout_alignParentLeft = "true"
android:layout_alignParentStart = "true" />
<Button
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Right"
android:id = "@+id/nextButton"
android:layout_alignParentBottom = "true"
android:layout_alignParentRight = "true"
android:layout_alignParentEnd = "true" />
ошибка :
05-01 03:53:09.768 8768-8768/samcox.remotedroid E/InputEventReceiver: Exception dispatching input event.
05-01 03:53:09.775 8768-8768/samcox.remotedroid E/AndroidRuntime: FATAL EXCEPTION: main
Process: samcox.remotedroid, PID: 8768
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:116)
at java.net.SocketOutputStream.write(SocketOutputStream.java:161)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at java.io.PrintWriter.newLine(PrintWriter.java:482)
at java.io.PrintWriter.println(PrintWriter.java:629)
at java.io.PrintWriter.println(PrintWriter.java:740)
at samcox.remotedroid.MainActivity$1.onTouch(MainActivity.java:77)
at android.view.View.dispatchTouchEvent(View.java:13468)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:731)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1869)
at android.app.Activity.dispatchTouchEvent(Activity.java:3487)
at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:689)
at android.view.View.dispatchPointerEvent(View.java:13720)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6125)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5903)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5352)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5405)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5371)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5530)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5379)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5587)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5352)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5405)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5371)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5379)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5352)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8412)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8345)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8298)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8527)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:198)
at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:187)
at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:8486)
05-01 03:53:09.776 8768-8768/samcox.remotedroid E/AndroidRuntime: at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:8554)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:690)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7073)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
Я новичок в программировании, так что извините за ошибки
Возможный дубликат как исправить FATAL EXCEPTION: main android.os.NetworkOnMainThreadException
Пожалуйста, не повторяйте тот же вопрос. Отредактируйте старый вопрос с новыми данными.
Мне жаль. Я буду делать это с этого момента.
Дубликат stackoverflow.com/questions/6343166/…
Возможный дубликат Как исправить исключение android.os.NetworkOnMainThreadException?
Проблема в том, что внутри onPostExecute AsyncTask вы вызываете следующее:
socket.getOutputStream()
Это происходит в MainThread, поэтому возникает исключение. Переместите его в doInBackground внутри try catch block, чтобы он выглядел так:
public class ConnectPhoneTask extends AsyncTask<String,Void,Boolean> {
@Override
protected Boolean doInBackground(String... params) {
boolean result = true;
try {
InetAddress serverAddr = InetAddress.getByName(params[0]);
socket = new Socket(serverAddr, Constants.SERVER_PORT);//Open socket on server IP and port
if (isConnected) {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true); //create output stream to send data to server
}
} catch (IOException e) {
Log.e("remotedroid", "Error while connecting", e);
result = false;
}
return result;
}
@Override
protected void onPostExecute(Boolean result)
{
isConnected = result;
Toast.makeText(context,isConnected?"Connected to server!":"Error while connecting",Toast.LENGTH_LONG).show();
}
}
Спасибо за ваш ответ, но я переместил socket.getOutputStream() в doInBackground, и возникла та же ошибка. Есть ли проблемы с другой частью?
Часть, которая передает данные на сервер, работала в основном потоке. Спасибо. Это было действительно полезно.
Я рекомендую, когда вы получаете ошибки, вы не уверены в том, что их вызывает, вы должны разбить сложные инструкции на простые инструкции и установить точку останова, чтобы вы могли просмотреть их и точно увидеть, какая инструкция приводит к ошибке во время выполнения. Итак, в приведенном выше коде вы могли бы упростить его так:
OutputStream os = socket.getOutputStream();
OutputStreamWriter ow = new OutputStreamWriter(os);
out = new PrintWriter(ow, true); //create output stream to send data to server
Это означает, что вы выполняете сетевую операцию в основном потоке. В postExecute вы отправляете сетевой поток в свой основной поток. OnPostExecute всегда вызывается в основном потоке.