1

I created a singleton class to enable socket connection, which returns a socket object, which can be used by any number of activities in the application. the singleton class is as follows

public class Singleton 
{
private static Socket socket;
private DataInputStream input;
private DataOutputStream output;
private boolean logged;
private static Singleton instance;
private String information;
private static final int SERVERPORT = 8020;
private static final String SERVER_IP = "192.168.1.33";
static PrintWriter out;

private Singleton()
{
}

public static Singleton getInstance()
{
        return instance;
}

public static void initSingleton()
{
    if(instance == null)
    {
        instance = new Singleton();
        InetAddress serverAddr = null;
        try {
            serverAddr = InetAddress.getByName(SERVER_IP);
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            socket = new Socket(serverAddr, SERVERPORT);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
        try {
            out = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(socket.getOutputStream())),
                    true);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}



public Socket getSocket()
{
    return socket;
}


public PrintWriter getOutput()
{
    return out;
}

}

In the MainActivity, I call the singleton class.

public class MainActivity extends Activity implements OnItemSelectedListener {
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);     
    initSingleton(); }
protected void initSingleton()
{
    Singleton.initSingleton();
}
public void onClickon(View view) {
    Socket socket = Singleton.getInstance().getSocket();

    try{

        PrintWriter out=Singleton.getInstance().getOutput();    
    out.println("0"); 
    }
    catch (Exception e) {
        e.printStackTrace();
    }

}
  }

on button click , the onClickon function is called which uses the the getSocket() and getOutput() functions of the Singleton class to return the object types.

But the application crashes.

The log is as follows.

05-08 11:33:41.236: E/AndroidRuntime(19813): FATAL EXCEPTION: main
05-08 11:33:41.236: E/AndroidRuntime(19813): Process: com.example.clientmobile2, PID: 19813
05-08 11:33:41.236: E/AndroidRuntime(19813): java.lang.RuntimeException: Unable to start activity     ComponentInfo{com.example.clientmobile2/com.example.clientmobile2.MainActivity}: android.os.NetworkOnMainThreadException
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2209)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2269)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.app.ActivityThread.access$800(ActivityThread.java:139)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.os.Handler.dispatchMessage(Handler.java:102)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.os.Looper.loop(Looper.java:136)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.app.ActivityThread.main(ActivityThread.java:5102)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at java.lang.reflect.Method.invokeNative(Native Method)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at java.lang.reflect.Method.invoke(Method.java:515)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at dalvik.system.NativeStart.main(Native Method)
05-08 11:33:41.236: E/AndroidRuntime(19813): Caused by: android.os.NetworkOnMainThreadException
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at libcore.io.IoBridge.connect(IoBridge.java:112)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at java.net.Socket.startupSocket(Socket.java:566)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at java.net.Socket.<init>(Socket.java:226)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at com.example.clientmobile2.Singleton.initSingleton(Singleton.java:48)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at com.example.clientmobile2.MainActivity.initSingleton(MainActivity.java:148)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at com.example.clientmobile2.MainActivity.onCreate(MainActivity.java:101)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.app.Activity.performCreate(Activity.java:5248)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
05-08 11:33:41.236: E/AndroidRuntime(19813):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2173)
apxcode
  • 7,696
  • 7
  • 30
  • 41
shivram
  • 469
  • 2
  • 10
  • 26

4 Answers4

2

One main thing is that you cannot run Costly operations on main thread like Remote Connection.. e.t.c, I mean that you create new thread for this socket connection else use Asynchronous task will reslove your issue.

Note: Please don't forget to close the connection

Sainath Patwary karnate
  • 3,165
  • 1
  • 16
  • 18
1

This code:

protected void initSingleton()
{
    Singleton.initSingleton();
}

Is not executing before you try to get the instance, even if you are calling that function onCreate(). Why are you instantiating the Singleton on a separate method instead of instantiating it inside the getInstance()?

Change your code to look like this to avoid this kind of problem when you call the Singleton and the instance doesn't exist.

public static Singleton getInstance()
{
     if(instance == null)
        initSingleton();

     return instance;
}

private static void initSingleton()
{
     instance = new Singleton();
     InetAddress serverAddr = null;
     try 
     {
         serverAddr = InetAddress.getByName(SERVER_IP);
     } 
     catch (UnknownHostException e) 
     {
         System.err.println("Fail when getting Server Address.");
     }
     try 
     {
         socket = new Socket(serverAddr, SERVERPORT);
     } 
     catch (IOException e) 
     {
         System.err.println("Failed creating new socket.");
     }  
     try 
     {
         out = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(socket.getOutputStream())),
                    true);
     } 
     catch (IOException e) 
     {
          System.err.println("EPIC FAIL HERE"); 
     }
}

Main activity:

public class MainActivity extends Activity implements OnItemSelectedListener 
{
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     
    }

    public void onClickon(View view) 
    {
        Socket socket = Singleton.getInstance().getSocket();
        try
        {
           PrintWriter out=Singleton.getInstance().getOutput();    
           out.println("0"); 
        }
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }
  }
apxcode
  • 7,696
  • 7
  • 30
  • 41
  • hey thanks for the reply. The application is still crashing. I checnged the Singleton.Java code as per your answer. Do i need to make any changes in the MainActivity.java? @FunctionR – shivram May 08 '14 at 06:26
  • Try it now. If it still throws an error please post it if it is different. If it does throw an error during execution then the problem is in the way you are creating your `socket`. – apxcode May 08 '14 at 06:59
  • I also changed your catch statements so that you can know where the code is failing without having to read a bunch of stack trace. – apxcode May 08 '14 at 07:05
  • thanks again for the help! The application crashes again. is it because you are not calling the initSingleton() method? – shivram May 08 '14 at 07:08
  • When I call `Singleton.getInstance().getSocket();` the getInstance method calls the `initSingleton()` so the Singleton gets created. What printed when it crashed? – apxcode May 08 '14 at 07:14
  • the application launches successfully, but when the button is clicked it crashes. It says that it is caused by InvocationTargetException and NetworkOnMainThreadException. – shivram May 08 '14 at 07:17
  • Did you copy my new version of `private static void initSingleton()` which has different error messages? They should print in red. – apxcode May 08 '14 at 07:19
  • yes i did.The three exceptions you created, did not print anything on LogCat. – shivram May 08 '14 at 07:22
  • When I run it the code fails to create a new socket. On this line: `socket = new Socket(serverAddr, SERVERPORT);` – apxcode May 08 '14 at 07:37
  • that is probably happening because you are not running the server program. I am runnning the server program, and i try to establish a connection, but it crashes and does not return failed to create new socket – shivram May 08 '14 at 07:39
  • I ran it with `socket = new Socket("www.google.com", 80);` and it worked fine, no crashes. – apxcode May 08 '14 at 07:41
  • this is bad.its not working even when i changed to socket = new Socket("www.google.com", 80); . It still crashes – shivram May 08 '14 at 08:11
  • Weird, could the crash be due to some other code? I can run it just fine. – apxcode May 09 '14 at 00:59
0

FunctionR's solution is correct, but it is not thread safe, so one solution can be to instantiate the singleton variable in a static initializer or to use synchronized blocks to make the singleton instantiation thread safe (http://www.jguru.com/faq/view.jsp?EID=124425).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
gorefest
  • 849
  • 8
  • 22
0

hi i tried our code and i did some modification and it work fine forme , i instantiate the socket and implement initSingleton() in athead that in execute MainActivity

public class ConnectActivity extends Activity {
    Socket clientSocket;
    Singleton instance;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_connect);
        instance=new Singleton();

        new Thread(new ClientThread()).start();
        //Socket socket = Singleton.getInstance().getSocket();

    }
    protected void initSingleton()
    {
        instance.initSingleton();
    }
   
    class ClientThread implements Runnable {
        @Override
        public void run() {

                initSingleton();
                Socket socket = Singleton.getInstance().getSocket();
            }
    }

Singleton()

public class Singleton {
    public static Socket clientSocket;
    /* private DataInputStream input;
     private DataOutputStream output;*/
    private boolean logged;
    public static Singleton instance;
    public static String information;
    public static int SERVER_PORT;
    public static String SERVER_IP;
    /*static PrintWriter out;*/

    public Singleton() {
    }

    public Singleton(int server_port, String server_ip) {
        SERVER_PORT = server_port;
        SERVER_IP = server_ip;

    }

    public static Singleton getInstance() {
        return instance;
    }

    public static void initSingleton() {
        if (instance == null) {
            instance = new Singleton();
            InetAddress serverAddr = null;
            try {
                serverAddr = InetAddress.getByName(SERVER_IP);
                information=SERVER_IP;
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            try {
                clientSocket = new Socket(information, SERVER_PORT);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        }
    }

    public Socket getSocket() {
        return clientSocket;
    }
}

i changed the code to for my project but i think u could use the modification to run your's`