1

I'm working on an little app, that gets the current geo coordinates and returns the relevant address with json objects. Here is the problem: If I run app on Samsung Galaxy S, it works perfectly, however, if I run it on Galaxy S3, there happens a run time error, such that, it gets the current location coordinates but cannot retrieve json object. The code is as following:

package com.demobasar;

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;

import android.os.Bundle;

import android.widget.TextView;
import android.widget.Toast;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MainActivity extends ActionBarActivity implements LocationListener {
    TextView longT, latT, ulke, sehir, ilce, sokak, mahalle;
    private LocationManager locationManager;
    private String provider;
    Location location;
    double lat, lng;

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

        longT = (TextView) findViewById(R.id.longT);
        latT = (TextView) findViewById(R.id.lat);
        ulke = (TextView) findViewById(R.id.ulke);
        sehir = (TextView) findViewById(R.id.sehir);
        ilce = (TextView) findViewById(R.id.ilce);
        sokak = (TextView) findViewById(R.id.sokak);
        mahalle =(TextView) findViewById(R.id.mahalle);

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        Criteria criteria = new Criteria();
        provider = locationManager.getBestProvider(criteria, false);
        location = locationManager.getLastKnownLocation(provider);

        if (location != null) {
            onLocationChanged(location);
        } else {
            longT.setText("Location not available");
            latT.setText("Location not available");
        }
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {

                    try {
                        ulke.setText(getJson("http://maps.basarsoft.com.tr/yb5.ashx?f=rg&x=" + lng + "&y=" +lat).getString("Order0"));
                        sehir.setText(getJson("http://maps.basarsoft.com.tr/yb5.ashx?f=rg&x=" + lng + "&y=" +lat).getString("Order1"));
                        ilce.setText(getJson("http://maps.basarsoft.com.tr/yb5.ashx?f=rg&x=" + lng + "&y=" +lat).getString("Order8"));
                        mahalle.setText(getJson("http://maps.basarsoft.com.tr/yb5.ashx?f=rg&x=" + lng + "&y=" +lat).getString("Order9"));
                        sokak.setText(getJson("http://maps.basarsoft.com.tr/yb5.ashx?f=rg&x=" + lng + "&y=" +lat).getString("Street"));
                    } catch (JSONException e) {
                         e.printStackTrace();

                    }

            }
        }, 10000);

    }
    @Override
    protected void onResume() {
        super.onResume();
        locationManager.requestLocationUpdates(provider, 400, 1, this);
    }
    @Override
    protected void onPause() {
        super.onPause();
        locationManager.removeUpdates(this);
    }
    @Override
    public void onLocationChanged(Location location) {
        lat = location.getLatitude();
        lng = location.getLongitude();
        longT.setText("" + lng);
        latT.setText("" + lat);
    }
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onProviderEnabled(String provider) {
        Toast.makeText(this, "Enabled new provider " + provider,
                Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onProviderDisabled(String provider) {
        Toast.makeText(this, "Disabled provider " + provider,
                Toast.LENGTH_SHORT).show();
    }
    public static JSONObject getJson(String url){

        InputStream is = null;
        String result = "";
        JSONObject jsonObject = null;

        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpGet httppost = new HttpGet(url);
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();
        } catch(Exception e) {
            return null;
        }
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"utf-8"),8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            result = sb.toString();
        } catch(Exception e) {
            return null;
        }
        try {
            jsonObject = new JSONObject(result);
        } catch(JSONException e) {
            return null;
        }
        return jsonObject;
    }
}

And android manifest is as follows:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.demobasar"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="19" />
        <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.demobasar.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Finally LogCat:

01-19 22:01:14.689  23948-23948/com.demobasar E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NullPointerException
            at com.demobasar.MainActivity$1.run(MainActivity.java:68)
            at android.os.Handler.handleCallback(Handler.java:730)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:176)
            at android.app.ActivityThread.main(ActivityThread.java:5419)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
            at dalvik.system.NativeStart.main(Native Method)
user2604150
  • 379
  • 5
  • 18
  • This is NetworkOnMainThreadException, masked by an `getJson()` exception handler not logging the exception and just returning null. – laalto Jan 19 '14 at 20:12
  • possible duplicate of [android.os.NetworkOnMainThreadException](http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception) – laalto Jan 19 '14 at 20:12
  • @laalto what should I do? I have been working on it more than 2 hours. – user2604150 Jan 19 '14 at 20:13
  • You should run HTTP requests a in a new thread (asynctask etc.) – Marco Acierno Jan 19 '14 at 20:16
  • @user2604150 First fix the exception logging to actually see your problem. Then see the linked question for more info how to implement an async task. Then move the networking code to the async task's `doInBackground()`. – laalto Jan 19 '14 at 20:31

1 Answers1

1

Since API 3.0 Android is throwing NetworkOnMainThreadException if you do any network stuff on GUI thread, and this is what you are doing in your handler (it was created on GUI thread so it runs on GUI thread). Galaxy S comes with Android 2.x, which does not throw this exception.

NetworkOnMainThreadException is probably somewhere deeper in your logcat

the usual solution is to put network operation into AsyncTask

for reference http://www.androiddesignpatterns.com/2012/06/app-force-close-honeycomb-ics.html

marcinj
  • 48,511
  • 9
  • 79
  • 100
  • @Ascorbin A runnable can run anywhere. When posted to UI thread's handler as in the question, it'll run on the UI thread. – laalto Jan 19 '14 at 20:31