0

I am developing an Android app. In my app, I am using Retrofit network library to connect with server. This is my very first time of using retrofit. Before I was using Volley. So before I use retrofit in real project, I am testing it making a simple get request to server.

I installed retrofit in Gradle

compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

I created a interface for retrofit request

public interface RetrofitService {
    @GET("test")
    Call<ChildCategoryItem> repoContributors();

    public static final Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(LinkConfig.API_END_POINT)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
}

I made request in activity like this

 private void makeRetrofitRequest()
    {
        try{
            RetrofitService service = RetrofitService.retrofit.create(RetrofitService.class);
            Call<ChildCategoryItem> call = service.repoContributors();
            String result = call.execute().body().toString();
            Toast.makeText(getBaseContext(),result,Toast.LENGTH_SHORT).show();
        }
        catch (IOException e)
        {
            Toast.makeText(getBaseContext(),"Exception",Toast.LENGTH_SHORT).show();
        }
    }

Server is returning this json data

{"id":1,"name":"name","mm_name":"mm_name"}

This is my ChildCategoryItem class

public class ChildCategoryItem {
    private int Id;
    private String Name;
    private String MmName;
    private int ParentId;

    public void setId(int id)
    {
        this.Id = id;
    }
    public int getId()
    {
        return this.Id;
    }
    public void setName(String name)
    {
        this.Name = name;
    }
    public String getName()
    {
        return this.Name;
    }
    public void setMmName(String mmName)
    {
        this.MmName = mmName;
    }
    public String getMmName()
    {
        return this.MmName;
    }
    public void setParentId(int id)
    {
        this.ParentId = id;
    }
    public int getParentId()
    {
        return this.ParentId;
    }


    public static ChildCategoryItem fromJson(JSONObject json)
    {
        try{
            ChildCategoryItem item = new ChildCategoryItem();
            item.setId(json.getInt("id"));
            item.setName(json.getString("name"));
            item.setMmName(json.getString("mm_name"));
            return item;
        }
        catch (JSONException e)
        {
            return null;
        }
    }
}

When I run, it gives me this error

08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime: FATAL EXCEPTION: main
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{mmbookhub.com.mmbookhub/mmbookhub.com.mmbookhub.ContributeActivity}: android.os.NetworkOnMainThreadException
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread.access$600(ActivityThread.java:141)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:137)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5103)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:525)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:  Caused by: android.os.NetworkOnMainThreadException
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1133)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at libcore.io.IoBridge.connectErrno(IoBridge.java:144)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at libcore.io.IoBridge.connect(IoBridge.java:112)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at java.net.Socket.connect(Socket.java:842)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.AndroidPlatform.connectSocket(AndroidPlatform.java:55)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:185)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.RealCall.getResponse(RealCall.java:243)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at okhttp3.RealCall.execute(RealCall.java:57)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:89)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at mmbookhub.com.mmbookhub.ContributeActivity.makeRetrofitRequest(ContributeActivity.java:505)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at mmbookhub.com.mmbookhub.ContributeActivity.onCreate(ContributeActivity.java:84)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:5133)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread.access$600(ActivityThread.java:141) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:137) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5103) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:525) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
08-20 05:24:41.195 1341-1341/mmbookhub.com.mmbookhub E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method) 
08-20 05:24:41.231 398-410/system_process W/ActivityManager:   Force finishing activity mmbookhub.com.mmbookhub/.ContributeActivity
08-20 05:24:41.231 398-410/system_process W/ActivityManager:   Force finishing activity mmbookhub.com.mmbookhub/.MainActivity

What is wrong with my code? Is this the way I making request correct?

halfer
  • 19,824
  • 17
  • 99
  • 186
Wai Yan Hein
  • 13,651
  • 35
  • 180
  • 372
  • Possible duplicate of [How to fix android.os.NetworkOnMainThreadException?](http://stackoverflow.com/questions/6343166/how-to-fix-android-os-networkonmainthreadexception) – Viktor Yakunin Aug 20 '16 at 09:56

4 Answers4

1

error is happened due to android does not support network on main thread you can solve it by putting your network call in new thread

or use below method for your case

 call.enqueue(new Callback<ChildCategoryItem>() {
        @Override
        public void onResponse(Call<ChildCategoryItem> call, Response<ChildCategoryItem> response) {

        }

        @Override
        public void onFailure(Call<ChildCategoryItem> call, Throwable t) {
             t.printStackTrace();
        }
    });
Manthan Patel
  • 993
  • 1
  • 9
  • 20
1

You have 2 options :

  1. Put your api call inside seperate Thread

    String result = call.execute().body().toString(); //put this inside seperate Thread
    
  2. Use enqueue() of Retrofit.

    call.enqueue(new Callback<ChildCategoryItem>() {
        @Override
        public void onResponse(Call<ChildCategoryItem> call, Response<ChildCategoryItem> response) {
               //Here you will get your response.
        }
    
        @Override
        public void onFailure(Call<ChildCategoryItem> call, Throwable t) {
             t.printStackTrace();
        }
    });
    

You must check this for NetworkOnMainThreadException

Community
  • 1
  • 1
Ravi
  • 34,851
  • 21
  • 122
  • 183
  • Thank you. I can use this. But having a problem. When I retrieve category name like this ChildCategoryItem item = response.body(); Toast.makeText(getBaseContext(),item.getName(),Toast.LENGTH_SHORT).show(); , it is always empty. But the server is returning exactly a value, Please why? How can I solve it? – Wai Yan Hein Aug 20 '16 at 10:32
  • better to check `response.isSuccessful()` before parsing/using its data. If everything is perfect, check for your model class and its value – Ravi Aug 20 '16 at 10:34
  • In volley, we have to create singleton class to prevent out of memory exception. In retrofit, do I need to create it like in volley? Does the way I am doing prevent that error please? – Wai Yan Hein Aug 20 '16 at 10:41
  • I already checked success or not as u mentioned. Response is success. But the value is empty. Please what is the possible error? – Wai Yan Hein Aug 20 '16 at 10:46
1

In place of call.execute() use call.enqueue() to make an asynchronous request. (other than ui thread). execute() is synchronous call perform on same thread i.e. ui thread.

Ramit
  • 416
  • 3
  • 8
1

As pointed by Viktor Yakunin you should go through the following link as main problem is making network call no UI thread.

How to fix android.os.NetworkOnMainThreadException?

According to Retrofit Documentation

Call instances can be executed either synchronously or asynchronously. Each instance can only be used once, but calling clone() will create a new instance that can be used.

On Android, callbacks will be executed on the main thread. On the JVM, callbacks will happen on the same thread that executed the HTTP request.

For synchronous call we use

call.execute

For asynchronous call we use

call.enqueue

I have not used volley, but if you are starting with retrofit I suggest you go through this:

Consuming APIs with Retrofit

For your program this is the easiest method:

ChildCategoryItem.java

public class ChildCategoryItem
{
@SerializedName("id")
@Expose
private String id;
@SerializedName("name")
@Expose
private String name;
@SerializedName("mm_name")
@Expose
private String mmName;

/**
 * @return The id
 **/
public String getId()
{
    return id;
}

/**
 * @param id The id
 **/
public void setId(String id)
{
    this.id = id;
}

 /**
 * @return The name
 **/
public String getName()
{
    return name;
}

/**
 * @param name The name
 **/
public void setName(String name)
{
    this.name = name;
}

/**
 * @return The mmName
 **/
public String getMmName()
{
    return mmName;
}

/**
 * @param mmName The mm_name
**/
public void setMmName(String mmName)
{
    this.mmName = mmName;
}
}

MainActivity.java

public class MainActivity extends AppCompatActivity
{

    String result;
    doRetrofit DD;
    Call<ChildCategoryItem> call;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DD= new doRetrofit();
        DD.execute();
    }

    public class doRetrofit extends AsyncTask
    {
        @Override
        protected Object doInBackground(Object[] objects)
        {
            String baseurl="http://192.168.1.12";
            Retrofit adapter= new Retrofit.Builder().baseUrl(baseurl).addConverterFactory(GsonConverterFactory.create()).build();
            RetrofitService retrofitService=adapter.create(RetrofitService.class);
            Call<ChildCategoryItem> call=retrofitService.repoContributors();
            Response<ChildCategoryItem> c= null;
            try
            {
                c = call.execute();
            } catch (IOException e)
            {
                e.printStackTrace();
            }
            Log.d("<<<<<<<<<Response>>>>>>",c.body().toString());
            ChildCategoryItem child=c.body();
            Log.d("<<<<<<<<<Response>>>>>>",child.getId());
            Log.d("<<<<<<<<<Response>>>>>>",child.getName());
            Log.d("<<<<<<<<<Response>>>>>>",child.getMmName());

            return null;
        }
    }
}

RetrofitService.java

public interface RetrofitService
{
    @GET("/loltry.php")
    Call<ChildCategoryItem> repoContributors();
}

As a matter of curosity, where and how are you using fromJson method?

Hope this helps :)

Since I can't comment due to lack of reputation, FYI: don't use toast in worker thread(i.e., in Asynctask doInBackground) toast should always be used with UI thread. see this:

Can't create handler inside thread that has not called Looper.prepare()

Community
  • 1
  • 1
Rushi M Thakker
  • 679
  • 2
  • 15
  • 34