1

I need to use FACEBOOK GRAPH API from my Android App. I downloaded Facebook SDK for Android and studied Samples given with SDK. I also studied one of the samples titled GraphApiSample. In this sample, A batch of requests are executed using the following method:

Request.executeBatchAndWait(Collection<Request> requests)

Well, Now I am trying to execute a single request but I am getting android.os.NetworkOnMainThreadException while executing request. So far I know this exception occurs when we wanna try to execute HTTP requests without using AsyncTask/Thread. But in FB sample "GraphApiSample", they executed request without any thread and it works good. Then what's wrong with my request ?

AndroidManifest.xml

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

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="16" />

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.firstfbandroidapp.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>
        <activity
            android:name="com.facebook.LoginActivity"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" />

        <meta-data
            android:name="com.facebook.sdk.ApplicationId"
            android:value="@string/app_id" />

        <activity
            android:name="com.example.firstfbandroidapp.AnotherActivity"
            android:label="@string/title_activity_another" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/welcome"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="TextView" />

    <Button
        android:id="@+id/login_with_fb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/welcome"
        android:layout_centerHorizontal="true"
        android:text="Login with Facebook" />

    <com.facebook.widget.LoginButton
        android:id="@+id/authButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/login_with_fb"
        android:layout_alignParentTop="true"
        android:layout_marginTop="47dp" />

    <Button
        android:id="@+id/execute_request"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/login_with_fb"
        android:layout_centerHorizontal="true"
        android:text="Execute Request" />

</RelativeLayout>

MainActivity.java

package com.example.firstfbandroidapp;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONObject;

import com.facebook.*;
import com.facebook.model.*;

import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.View.OnClickListener;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

    Button loginWithFB;
    Button executeRequest;

    private Session session;
    private Session.StatusCallback statusCallback = new SessionStatusCallback();

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

        loginWithFB = (Button) findViewById(R.id.login_with_fb);
        executeRequest = (Button) findViewById(R.id.execute_request);
        executeRequest.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                session = Session.getActiveSession();
                if (session.isOpened()) {
                    sendRequest();
                } else {
                    Toast.makeText(getApplicationContext(), "No Active Session", Toast.LENGTH_LONG).show();
                }
            }
        });

        session = Session.getActiveSession();
        if(session == null) {
            if(savedInstanceState != null) {
                session = Session.restoreSession(this, null, statusCallback, savedInstanceState);
            }
            if(session == null) {
                session = new Session(this);
            }
            Session.setActiveSession(session);
            Settings.addLoggingBehavior(LoggingBehavior.INCLUDE_ACCESS_TOKENS);
            if(session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
                session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
            }
        }
        updateView();
    }

    @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 void onStart() {
        super.onStart();
        Session.getActiveSession().addCallback(statusCallback);
    }

    @Override
    public void onStop() {
        super.onStop();
        Session.getActiveSession().removeCallback(statusCallback);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
    }

    private void sendRequest()
    {
        Session session = Session.getActiveSession();
        Request request = new Request(session, "me", null, HttpMethod.GET, new Request.Callback() {
            @Override
            public void onCompleted(Response response) {
                GraphObject graphObject = response.getGraphObject();
                FacebookRequestError error = response.getError();
                if (graphObject != null) {
                    JSONObject jsonObject = graphObject.getInnerJSONObject();
                    Log.d("MY_TAG", jsonObject.toString());
                    if (graphObject.getProperty("id") != null) {
                        Toast.makeText(getApplicationContext(), (String)graphObject.getProperty("id"), Toast.LENGTH_LONG).show();
                    }
                    //System.out.println(jsonObject.toString());
                }
            }
        });
        Request.executeAndWait(request);
    }

    private void updateView() {
        Session session = Session.getActiveSession();
        if (session.isOpened()) {
            loginWithFB.setText("Logout");
            loginWithFB.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onClickLogout();
                    loginWithFB.setText("Login with Facebook");
                }
            });
        } else {
            loginWithFB.setText("Login with Facebook");
            loginWithFB.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onClickLogin();
                }
            });
        }
    }

    private void onClickLogin() {
        Session session = Session.getActiveSession();
        if (!session.isOpened() && !session.isClosed()) {
            session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
        } else {
            Session.openActiveSession(this, true, statusCallback);
        }
    }

    private void onClickLogout() {
        Session session = Session.getActiveSession();
        if (!session.isClosed()) {
            session.closeAndClearTokenInformation();
        }
    }

    private class SessionStatusCallback implements Session.StatusCallback {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            updateView();
        }
    }
}
iamcrypticcoder
  • 2,609
  • 4
  • 27
  • 50
  • Have you tried to execute the request on an asynctask? – Giacomoni Feb 21 '14 at 18:19
  • Your question is very long. Almost all of what you have posted is unneccesary - how could a layout affect this? What you didn't post was your LogCat, if you had people could offer more specific help - looking at it would also have allowed you to figure out what is relevant to post – Nick Cardoso Feb 21 '14 at 18:23
  • no. I didn't try with AsyncTask but I used AsyncTask for executing various HTTP request. Now I will try with AsyncTask. @giacomoni – iamcrypticcoder Feb 21 '14 at 19:36

1 Answers1

1

This is only thrown for applications targeting the Honeycomb SDK (v11) or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. Since you use android:targetSdkVersion="16" (Jelly Bean), you have to run network operations on another thread.

nikis
  • 11,166
  • 2
  • 35
  • 45
  • Hi nikis. Right you are. I just noticed that FB samples defined minSdkVersion=8 and didn't set any targetSdkVersion. I tested my code with minSdkVersion=9 and it works. I am good with AsyncTask and let me try with AsyncTask. This is all about my stupidity. :( – iamcrypticcoder Feb 21 '14 at 19:42