-1

I am trying to make a fairly simple test app that prints the accelerometer's values on the only activity screen. But when I run it, it gives a Fatal Error: NetworkOnMainThreadException in main.

I have tried to follow what might be the cause of it and followed this question to remove the problem which is to put all the simulator calls in respective AsyncTask classes. But, I am still getting the error.

My MainActivity.java:

Import statements:

package com.example.chillii;

import org.openintents.sensorsimulator.hardware.Sensor;
import org.openintents.sensorsimulator.hardware.SensorEvent;
import org.openintents.sensorsimulator.hardware.SensorEventListener;
import org.openintents.sensorsimulator.hardware.SensorManagerSimulator;

import android.hardware.SensorManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

The 3 AsyncTask classes that are supposed to remove the aforementioned error:

class ConnectToSimulator extends AsyncTask<SensorManagerSimulator, Void, Void>
{

    @Override
    protected Void doInBackground(SensorManagerSimulator ... arg0) {
        try{
            arg0[0].connectSimulator();
        }
        catch(Exception E)
        {
            Log.i("ConnectTaskError: ", E.getMessage());
        }
        return null;
    }
}

class RegisterToSimulator extends AsyncTask<Object, Void, Void> {      
    @Override
    protected Void doInBackground(Object... sm) {
        try{
            ((SensorManagerSimulator) sm[0]).registerListener((SensorEventListener) sm[1], ((SensorManagerSimulator) sm[0]).getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);
        }catch(Exception e)
        {
            Log.i("error", e.getMessage());
        }
        return null;
    }
}

class UnregisterFromSimulator extends AsyncTask<Object, Void, Void> {      
    @Override
    protected Void doInBackground(Object... sm) {
        try{
            ((SensorManagerSimulator) sm[0]).unregisterListener((SensorEventListener) sm[1]);
        }catch(Exception e)
        {
            Log.i("error : ", e.getMessage());
        }
        return null;
    }
}

My MainActivity class. The three AsyncTask classes are called in onCreate(). onResume() and onPause() (follows documentation on SensorSimulator's wiki page). Also, implements onSensorChanged() where it prints the three values in respective TextViews:

public class MainActivity extends ActionBarActivity implements SensorEventListener {

    private SensorManagerSimulator mSensorManager;

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

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
        }

        mSensorManager = SensorManagerSimulator.getSystemService(this, SENSOR_SERVICE);
        new ConnectToSimulator().execute(mSensorManager);
        //mSensorManager.connectSimulator();
    }

    @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;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container,
                    false);
            return rootView;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        new RegisterToSimulator().execute(mSensorManager, this);
    }

    @Override
    protected void onPause() {
        new UnregisterFromSimulator().execute(mSensorManager, this);
        super.onPause();
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) {
        // Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent E) {
        TextView tv;
        tv = (TextView) findViewById(R.id.xbox);
        tv.setText(Double.toString(E.values[0]));

        tv = (TextView) findViewById(R.id.ybox);
        tv.setText(Double.toString(E.values[1]));

        tv = (TextView) findViewById(R.id.zbox);
        tv.setText(Double.toString(E.values[2]));
    }
}

This is fragment_main.xml. Mostly boilerplate + 3 TextViews that by default print X, Y and Z:

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView android:id="@+id/xbox"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="X" />

        <TextView android:id="@+id/ybox"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Y" />

        <TextView android:id="@+id/zbox"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Z" />
    </LinearLayout>

</LinearLayout>

EDIT:

The stack trace in logcat is as follows:

05-29 05:30:23.239: E/AndroidRuntime(2231): FATAL EXCEPTION: main
05-29 05:30:23.239: E/AndroidRuntime(2231): android.os.NetworkOnMainThreadException
05-29 05:30:23.239: E/AndroidRuntime(2231):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1133)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:163)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at libcore.io.IoBridge.recvfrom(IoBridge.java:506)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at java.io.InputStreamReader.read(InputStreamReader.java:244)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at java.io.BufferedReader.fillBuf(BufferedReader.java:130)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at java.io.BufferedReader.readLine(BufferedReader.java:354)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at org.openintents.sensorsimulator.hardware.SensorSimulatorClient.readSensor(SensorSimulatorClient.java:654)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at org.openintents.sensorsimulator.hardware.SensorSimulatorClient.readSensor(SensorSimulatorClient.java:571)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at org.openintents.sensorsimulator.hardware.SensorSimulatorClient.access$1000(SensorSimulatorClient.java:53)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at org.openintents.sensorsimulator.hardware.SensorSimulatorClient$1.handleMessage(SensorSimulatorClient.java:505)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at android.os.Looper.loop(Looper.java:137)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at android.app.ActivityThread.main(ActivityThread.java:5103)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at java.lang.reflect.Method.invokeNative(Native Method)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at java.lang.reflect.Method.invoke(Method.java:525)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
05-29 05:30:23.239: E/AndroidRuntime(2231):     at dalvik.system.NativeStart.main(Native Method)
Community
  • 1
  • 1
Anurag Kalia
  • 4,668
  • 4
  • 21
  • 28
  • 2
    Examine the stacktrace to learn exactly where in your code you're doing a network operation on the UI thread. – laalto May 27 '14 at 12:44
  • How can we examine stacktrace? They all seem to involve functions I haven't written. – Anurag Kalia May 27 '14 at 13:28
  • If you can't figure out yourself where the network operation is, post the full exception stacktrace here. – laalto May 28 '14 at 07:13

1 Answers1

2

because of you use fragment class and call async task in main activity class remove below lines

 mSensorManager = SensorManagerSimulator.getSystemService(this, SENSOR_SERVICE);
 new ConnectToSimulator().execute(mSensorManager);

from onCreate and put it in onActivityCreated() method in PlaceholderFragment class thats it...

Jayesh Khasatiya
  • 2,140
  • 1
  • 14
  • 15
  • I am not familiar with fragments! Can I not use it for now? This is my first app and I am trying to make it run. Or shall I just implement SensorEventListener in this Fragment rather than the Activity class? Sorry for sounding ignorant, but I have only just learnt about Activities. – Anurag Kalia May 27 '14 at 13:22
  • Moreover, the exception is still there. I have done as you said but modified the statements as written in onActivitychanged() as follows: super.onActivityCreated(B); MainActivity parentAct = ((MainActivity) getActivity()); parentAct.mSensorManager = SensorManagerSimulator.getSystemService(getActivity(), SENSOR_SERVICE); new ConnectToSimulator().execute(parentAct.mSensorManager); – Anurag Kalia May 27 '14 at 13:26
  • sorry! the comments don't seem to support newlines! To explain the jumble above, I have just used the getActivity() to access parent Activity from the fragment. – Anurag Kalia May 27 '14 at 13:26
  • ok just remove if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()).commit(); } code and put above two lines in onCreate also change setoncontentview(R.layout.activity_main) to setoncontentview(R.layout.fragment_main) – Jayesh Khasatiya May 27 '14 at 13:32
  • I did as you said. (And removed onActivityCreated() from the Fragment class to remove redundancy of the said two lines). The error persists! Moreover, why are we doing this shuffling; I mean is there a good resource that tells what exactly is a part of "main thread"? – Anurag Kalia May 27 '14 at 13:41
  • @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_main); mSensorManager = SensorManagerSimulator.getSystemService(this, SENSOR_SERVICE); new ConnectToSimulator().execute(mSensorManager); //mSensorManager.connectSimulator(); } – Jayesh Khasatiya May 27 '14 at 13:45
  • Yes, that is what I have written. Word to word. :-/ – Anurag Kalia May 27 '14 at 13:47
  • set your minimum sdk version to 9 and add this two line in oncreate just below setcontentview – Jayesh Khasatiya May 27 '14 at 13:52
  • StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); – Jayesh Khasatiya May 27 '14 at 13:52
  • yay! it works! I cannot believe it. :D After 3 whole days of headaches and whatnot. But can I know in summary what just happened, before I dive into the documentation? :) – Anurag Kalia May 27 '14 at 14:03
  • check below link you get idea why we use strictmode policy http://developer.android.com/reference/android/os/StrictMode.html – Jayesh Khasatiya May 27 '14 at 14:07
  • mark this ans as correct ans and upvote. – Jayesh Khasatiya May 27 '14 at 14:08
  • and I'm sorry to bother you this one last time, but who is going to update this answer? Shall I do it or you? I am not familiar with the protocol. I'll happily do it if you would want me to. :) – Anurag Kalia May 27 '14 at 14:11
  • Hey, I'm sorry but I have removed the 'correct answer' for the time being to invite more opinions regarding how to remove the error because internet is chock full of how not to misuse the two lines that I have used above. But I still thank you from the bottom of my heart! :) – Anurag Kalia May 27 '14 at 14:37