2015-12-07 705 views
6

Stavo cercando di utilizzare una classe che implementa un client WebSocket in Android. Ma ottengo il seguente errore:Qual è un modo semplice per implementare un client Websocket in Android? Il seguente esempio è corretto?

12-07 11:22:46.286 31579-31579/com.domain.wsocketchat W/System: ClassLoader referenced unknown path: /data/app/com.domain.wsocketchat-2/lib/arm 
12-07 11:22:46.392 31579-31579/com.domain.wsocketchat W/System.err: an error occurred:java.net.SocketException: socket failed: EACCES (Permission denied) 

La classe che sto usando segue:

import org.java_websocket.client.WebSocketClient; 
import org.java_websocket.drafts.Draft; 
import org.java_websocket.drafts.Draft_10; 
import org.java_websocket.handshake.ServerHandshake; 

import java.net.URI; 

public class EmptyClient extends WebSocketClient { 
    public EmptyClient(URI serverUri, Draft draft) { 
     super(serverUri, draft); 
    } 

    public EmptyClient(URI serverURI) { 
     super(serverURI); 
    } 

    @Override 
    public void onOpen(ServerHandshake handshakedata) { 
     System.out.println("new connection opened"); 
    } 

    @Override 
    public void onClose(int code, String reason, boolean remote) { 
     System.out.println("closed with exit code " + code + " additional info: " + reason); 
    } 

    @Override 
    public void onMessage(String message) { 
     System.out.println("received message: " + message); 
    } 

    @Override 
    public void onError(Exception ex) { 
     System.err.println("an error occurred:" + ex); 
    } 
} 

La classe è chiamata all'interno del onCreate():

WebSocketClient client = null; 
try { 
    client = new EmptyClient(new URI("ws://192.168.1.135:9000/server.php"), new Draft_10()); 
} catch (URISyntaxException e) { 
    e.printStackTrace(); 
} 
client.connect(); 

AndroidManifest:

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

Sdk: minSdkVersion 16

Qualcuno ha qualche idea, quello che potrebbe essere il problema? Sembra tutto a posto! Grazie in anticipo.

+3

è corretto votare-do una domanda anche senza leggerla prima? – Kreshnik

+0

..Può aiutarmi su questo..Sto anche lavorando su Socket..Può per favore suggerirmi meglio GRADLE/LIBRARY per questo..Grazie –

+0

Per quanto mi ricordo, non ho trovato alcun riferimento gradle in quel volta, ho appena usato "org.java_websocket". Puoi controllare questo: (https://github.com/elabs/mobile-websocket-example/tree/master/android/WebsocketExampleClientProject) progetto github, ma è comunque un po 'vecchio. Utilizza "org.java-websocket: Java-WebSocket: 1.3.0" come dipendenza. – Kreshnik

risposta

6

ho già risolto il problema utilizzando un'altra classe, che gestisce il client websocket:

import android.app.Activity; 
    import android.app.Fragment; 
    import android.os.Build; 
    import android.os.Bundle; 
    import android.util.Log; 
    import android.view.LayoutInflater; 
    import android.view.Menu; 
    import android.view.MenuItem; 
    import android.view.View; 
    import android.view.ViewGroup; 
    import android.widget.EditText; 
    import android.widget.TextView; 

    import org.java_websocket.client.WebSocketClient; 
    import org.java_websocket.handshake.ServerHandshake; 

    import java.net.URI; 
    import java.net.URISyntaxException; 

    public class MainActivity extends Activity { 
     private WebSocketClient mWebSocketClient; 

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

      connectWebSocket(); 

      if (savedInstanceState == null) { 
       getFragmentManager().beginTransaction() 
         .add(R.id.container, new PlaceholderFragment()) 
         .commit(); 
      } 
     } 


     @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 boolean onOptionsItemSelected(MenuItem item) { 
      // Handle action bar item clicks here. The action bar will 
      // automatically handle clicks on the Home/Up button, so long 
      // as you specify a parent activity in AndroidManifest.xml. 
      switch (item.getItemId()) { 
       case R.id.action_settings: 
        return true; 
      } 
      return super.onOptionsItemSelected(item); 
     } 

     /** 
     * A placeholder fragment containing a simple view. 
     */ 
     public static class PlaceholderFragment extends Fragment { 

      public PlaceholderFragment() { 
      } 

      @Override 
      public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) { 
       View rootView = inflater.inflate(R.layout.fragment_main, container, false); 
       return rootView; 
      } 
     } 

     private void connectWebSocket() { 
      URI uri; 
      try { 
       uri = new URI("ws://192.168.1.135:9000/"); 
      } catch (URISyntaxException e) { 
       e.printStackTrace(); 
       return; 
      } 

      mWebSocketClient = new WebSocketClient(uri) { 
       @Override 
       public void onOpen(ServerHandshake serverHandshake) { 
        Log.i("Websocket", "Opened"); 
        mWebSocketClient.send("Hello from " + Build.MANUFACTURER + " " + Build.MODEL); 
       } 

       @Override 
       public void onMessage(String s) { 
        final String message = s; 
        runOnUiThread(new Runnable() { 
         @Override 
         public void run() { 
          TextView textView = (TextView)findViewById(R.id.messages); 
          textView.setText(textView.getText() + "\n" + message); 
         } 
        }); 
       } 

       @Override 
       public void onClose(int i, String s, boolean b) { 
        Log.i("Websocket", "Closed " + s); 
       } 

       @Override 
       public void onError(Exception e) { 
        Log.i("Websocket", "Error " + e.getMessage()); 
       } 
      }; 
      mWebSocketClient.connect(); 
     } 

     public void sendMessage(View view) { 
      EditText editText = (EditText)findViewById(R.id.message); 
      mWebSocketClient.send(editText.getText().toString()); 
      editText.setText(""); 
     } 
    } 

Per chiunque sia interessato, ho usato un websocket-Chatserver scritto in PHP:

<?php 
$r = $_SERVER['SERVER_ADDR']; 
if($r=="::1") $r="localhost"; 

$host = $r; //'localhost'; //host 
$port = '9000'; //port 
$null = NULL; //null var 

//Create TCP/IP sream socket 
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
//reuseable port 
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1); 

//bind socket to specified host 
socket_bind($socket, 0, $port); 

//listen to port 
socket_listen($socket); 

//create & add listning socket to the list 
$clients = array($socket); 

//start endless loop, so that our script doesn't stop 
while (true) { 
    //manage multipal connections 
    $changed = $clients; 
    //returns the socket resources in $changed array 
    socket_select($changed, $null, $null, 0, 10); 

    //check for new socket 
    if (in_array($socket, $changed)) { 
     $socket_new = socket_accept($socket); //accpet new socket 
     $clients[] = $socket_new; //add socket to client array 

     $header = socket_read($socket_new, 1024); //read data sent by the socket 
     perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake 

     socket_getpeername($socket_new, $ip); //get ip address of connected socket 
     $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data 
     send_message($response); //notify all users about new connection 

     //make room for new socket 
     $found_socket = array_search($socket, $changed); 
     unset($changed[$found_socket]); 
    } 

    //loop through all connected sockets 
    foreach ($changed as $changed_socket) { 

     //check for any incomming data 
     while(socket_recv($changed_socket, $buf, 1024, 0) >= 1) 
     { 
      $received_text = unmask($buf); //unmask data 
      $tst_msg = json_decode($received_text); //json decode 
      $user_name = $tst_msg->name; //sender name 
      $user_message = $tst_msg->message; //message text 
      $user_color = $tst_msg->color; //color 

      //prepare data to be sent to client 
      $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color))); 
      send_message($response_text); //send data 
      break 2; //exist this loop 
     } 

     $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ); 
     if ($buf === false) { // check disconnected client 
      // remove client for $clients array 
      $found_socket = array_search($changed_socket, $clients); 
      socket_getpeername($changed_socket, $ip); 
      unset($clients[$found_socket]); 

      //notify all users about disconnected connection 
      $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected'))); 
      send_message($response); 
     } 
    } 
} 
// close the listening socket 
socket_close($sock); 

function send_message($msg) 
{ 
    global $clients; 
    foreach($clients as $changed_socket) 
    { 
     @socket_write($changed_socket,$msg,strlen($msg)); 
    } 
    return true; 
} 


//Unmask incoming framed message 
function unmask($text) { 
    $length = ord($text[1]) & 127; 
    if($length == 126) { 
     $masks = substr($text, 4, 4); 
     $data = substr($text, 8); 
    } 
    elseif($length == 127) { 
     $masks = substr($text, 10, 4); 
     $data = substr($text, 14); 
    } 
    else { 
     $masks = substr($text, 2, 4); 
     $data = substr($text, 6); 
    } 
    $text = ""; 
    for ($i = 0; $i < strlen($data); ++$i) { 
     $text .= $data[$i]^$masks[$i%4]; 
    } 
    return $text; 
} 

//Encode message for transfer to client. 
function mask($text) 
{ 
    $b1 = 0x80 | (0x1 & 0x0f); 
    $length = strlen($text); 

    if($length <= 125) 
     $header = pack('CC', $b1, $length); 
    elseif($length > 125 && $length < 65536) 
     $header = pack('CCn', $b1, 126, $length); 
    elseif($length >= 65536) 
     $header = pack('CCNN', $b1, 127, $length); 
    return $header.$text; 
} 

//handshake new client. 
function perform_handshaking($receved_header,$client_conn, $host, $port) 
{ 
    $headers = array(); 
    $lines = preg_split("/\r\n/", $receved_header); 
    foreach($lines as $line) 
    { 
     $line = chop($line); 
     if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)) 
     { 
      $headers[$matches[1]] = $matches[2]; 
     } 
    } 

    $secKey = $headers['Sec-WebSocket-Key']; 
    $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); 
    //hand shaking header 
    $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . 
    "Upgrade: websocket\r\n" . 
    "Connection: Upgrade\r\n" . 
    "WebSocket-Origin: $host\r\n" . 
    "WebSocket-Location: ws://$host:$port/demo/shout.php\r\n". 
    "Sec-WebSocket-Accept:$secAccept\r\n\r\n"; 
    socket_write($client_conn,$upgrade,strlen($upgrade)); 
} 

al fine di avviare il server websocket è necessario per eseguire un comando da console come questo: php -q myserver.php

+1

a volte questo è necessario, DRAFT 17: mWebSocketClient = new WebSocketClient (uri, new Draft_17()) {...}; –

+0

quale libreria viene utilizzata per WebSocketClient? –

+0

Queste due importazioni -> org.java_websocket.client.WebSocketClient; org.java_websocket.handshake.ServerHandshake; – Kreshnik

Problemi correlati