Pergunta

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)
Foi útil?

Solução

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

Outras dicas

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();
        }
    }
  }

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).

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`

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top