2017-06-05 30 views
0

我正在使用Nodejs和套接字編程實現一個聊天應用程序。如果我從我的Android應用程序發送消息,它應該顯示已連接到我的WebStorm終端,但是沒有任何事情發生。Android應用程序不使用套接字發送消息給本地主機服務器

index.js

var app = require('express')(); 
var http = require('http').Server(app); 
var io = require('socket.io')(http); 
app.get('/',function(req,res){ 
    res.sendFile(__dirname+'/index.html'); 
}) 
io.on('connection',function(socket){ 
    console.log('one user connected '+socket.id); 
    socket.on('message',function(data){ 
     var sockets = io.sockets.sockets; 
     // sockets.forEach(function(sock){ 
     // if(sock.id != socket.id) 
     // { 
     // sock.emit('message',data); 
     // } 
     // }) 
     socket.broadcast.emit('message', data); 
     console.log('message '+data); 
    }) 
    socket.on('disconnect',function(){ 
     console.log('one user disconnected '+socket.id); 
    }) 
}) 

http.listen(3000,function(){ 
    console.log('server listening on port 3000'); 
}) 

的index.html

<!doctype html> 
<html> 
<head> 
    <title>Socket.IO chat</title> 
    <style> 
     * { margin: 0; padding: 0; box-sizing: border-box; } 
     body { font: 13px Helvetica, Arial; } 
     form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; } 
     form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; } 
     form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; } 
     #messages { list-style-type: none; margin: 0; padding: 0; } 
     #messages li { padding: 5px 10px; } 
     #messages li:nth-child(odd) { background: #eee; } 
    </style> 
</head> 
<body> 
<ul id="messages"></ul> 
<form action=""> 
    <input id="m" autocomplete="off" /><button>Send</button> 
</form> 
<script src="/socket.io/socket.io.js"></script> 
<script> 
    var socket = io(); 
</script> 
</body> 
<h1>Hello Sockets</h1> 
</html> 

ChatFragment.java

package com.example.admin.chatapp; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.net.Uri; 
import android.os.Bundle; 
import android.app.Fragment; 
import android.support.v7.widget.LinearLayoutManager; 
import android.support.v7.widget.RecyclerView; 
import android.util.Base64; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.EditText; 
import android.widget.ImageButton; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.net.URISyntaxException; 
import java.util.ArrayList; 
import java.util.List; 
import org.json.JSONException; 
import org.json.JSONObject; 

import io.socket.client.IO; 
import io.socket.client.Socket; 
import io.socket.emitter.Emitter; 


/** 
* A simple {@link Fragment} subclass. 
* Activities that contain this fragment must implement the 
* {@link ChatFragment.OnFragmentInteractionListener} interface 
* to handle interaction events. 
* Use the {@link ChatFragment#newInstance} factory method to 
* create an instance of this fragment. 
*/ 
public class ChatFragment extends Fragment { 
    // TODO: Rename parameter arguments, choose names that match 
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER 
    private static final String ARG_PARAM1 = "param1"; 
    private static final String ARG_PARAM2 = "param2"; 

    // TODO: Rename and change types of parameters 
    private String mParam1; 
    private String mParam2; 
    private EditText mInputMessageView; 
    private RecyclerView mMessagesView; 
    private OnFragmentInteractionListener mListener; 
    private List<Message> mMessages = new ArrayList<Message>(); 
    private RecyclerView.Adapter mAdapter; 

    private Socket socket; 
    { 
     try{ 
      socket = IO.socket("http://192.168.x.x:3000"); 
     }catch(URISyntaxException e){ 
      throw new RuntimeException(e); 
     } 
    } 
    /** 
    * Use this factory method to create a new instance of 
    * this fragment using the provided parameters. 
    * 
    * @param param1 Parameter 1. 
    * @param param2 Parameter 2. 
    * @return A new instance of fragment ChatFragment. 
    */ 
    // TODO: Rename and change types and number of parameters 
    public static ChatFragment newInstance(String param1, String param2) { 
     ChatFragment fragment = new ChatFragment(); 
     Bundle args = new Bundle(); 
     args.putString(ARG_PARAM1, param1); 
     args.putString(ARG_PARAM2, param2); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    public ChatFragment() { 
     // Required empty public constructor 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setHasOptionsMenu(true); 
     socket.connect(); 
     socket.on("message", handleIncomingMessages); 
    } 



    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     return inflater.inflate(R.layout.fragment_chat, container, false); 
    } 

    // TODO: Rename method, update argument and hook method into UI event 
    public void onButtonPressed(Uri uri) { 
     if (mListener != null) { 
      mListener.onFragmentInteraction(uri); 
     } 
    } 

    @Override 
    public void onAttach(Context activity) { 
     super.onAttach(activity); 
     mAdapter = new MessageAdapter(mMessages); 
     /*try { 
      mListener = (OnFragmentInteractionListener) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
        + " must implement OnFragmentInteractionListener"); 
     }*/ 

    } 

    @Override 
    public void onViewCreated(View view, Bundle savedInstanceState) { 
     super.onViewCreated(view, savedInstanceState); 

     mMessagesView = (RecyclerView) view.findViewById(R.id.messages); 
     mMessagesView.setLayoutManager(new LinearLayoutManager(getActivity())); 
     mMessagesView.setAdapter(mAdapter); 

     ImageButton sendButton = (ImageButton) view.findViewById(R.id.send_button); 
     mInputMessageView = (EditText) view.findViewById(R.id.message_input); 

     sendButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       sendMessage(); 
      } 
     }); 


    } 

    private void sendMessage(){ 
     String message = mInputMessageView.getText().toString().trim(); 
     mInputMessageView.setText(""); 
     addMessage(message); 
     JSONObject sendText = new JSONObject(); 
     try{ 
      sendText.put("text",message); 
      socket.emit("message", sendText); 
     }catch(JSONException e){ 

     } 

    } 

    public void sendImage(String path) 
    { 
     JSONObject sendData = new JSONObject(); 
     try{ 
      sendData.put("image", encodeImage(path)); 
      Bitmap bmp = decodeImage(sendData.getString("image")); 
      addImage(bmp); 
      socket.emit("message",sendData); 
     }catch(JSONException e){ 

     } 
    } 

    private void addMessage(String message) { 

     mMessages.add(new Message.Builder(Message.TYPE_MESSAGE) 
       .message(message).build()); 
     // mAdapter = new MessageAdapter(mMessages); 
     mAdapter = new MessageAdapter(mMessages); 
     mAdapter.notifyItemInserted(0); 
     scrollToBottom(); 
    } 

    private void addImage(Bitmap bmp){ 
     mMessages.add(new Message.Builder(Message.TYPE_MESSAGE) 
       .image(bmp).build()); 
     mAdapter = new MessageAdapter(mMessages); 
     mAdapter.notifyItemInserted(0); 
     scrollToBottom(); 
    } 
    private void scrollToBottom() { 
     mMessagesView.scrollToPosition(mAdapter.getItemCount() - 1); 
    } 

    private String encodeImage(String path) 
    { 
     File imagefile = new File(path); 
     FileInputStream fis = null; 
     try{ 
      fis = new FileInputStream(imagefile); 
     }catch(FileNotFoundException e){ 
      e.printStackTrace(); 
     } 
     Bitmap bm = BitmapFactory.decodeStream(fis); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     bm.compress(Bitmap.CompressFormat.JPEG,100,baos); 
     byte[] b = baos.toByteArray(); 
     String encImage = Base64.encodeToString(b, Base64.DEFAULT); 
     //Base64.de 
     return encImage; 

    } 

    private Bitmap decodeImage(String data) 
    { 
     byte[] b = Base64.decode(data,Base64.DEFAULT); 
     Bitmap bmp = BitmapFactory.decodeByteArray(b,0,b.length); 
     return bmp; 
    } 
    private Emitter.Listener handleIncomingMessages = new Emitter.Listener(){ 
     @Override 
     public void call(final Object... args){ 
      getActivity().runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        Log.d("cdcdc", String.valueOf(args[0])); 
        JSONObject data = (JSONObject) args[0]; 
        Log.d("cdcdc", String.valueOf(data)); 
        String message; 
        String imageText; 
        try { 
         message = data.getString("text").toString(); 
         addMessage(message); 

        } catch (JSONException e) { 
         // return; 
        } 
        try { 
         imageText = data.getString("image"); 
         addImage(decodeImage(imageText)); 
        } catch (JSONException e) { 
         //retur 
        } 

       } 
      }); 
     } 
    }; 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mListener = null; 
    } 

    /** 
    * This interface must be implemented by activities that contain this 
    * fragment to allow an interaction in this fragment to be communicated 
    * to the activity and potentially other fragments contained in that 
    * activity. 
    * <p/> 
    * See the Android Training lesson <a href= 
    * "http://developer.android.com/training/basics/fragments/communicating.html" 
    * >Communicating with Other Fragments</a> for more information. 
    */ 
    public interface OnFragmentInteractionListener { 
     // TODO: Update argument type and name 
     public void onFragmentInteraction(Uri uri); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     socket.disconnect(); 
    } 

} 

要運行不知疲倦x.js在WebStorm文件,我鍵入命令index.js

這使我的輸出作爲

服務器偵聽端口3000

節點當我從我的應用程序發送消息時,沒有任何反應。終端保持原樣。我該怎麼做,是什麼原因造成的。

更新 我改變了我的Android代碼

socket = IO.socket("http://01e42de0.ngrok.io"); 

使用ngrok給我一個錯誤

06-05 20:27:52.578 23204-23204/com.example.admin .chatapp E/AndroidRuntime:致命例外:main

進程:com.example.admin.chatapp,PID:23204 java.lang.RuntimeException:無法啓動活動 ComponentInfo {com.example.admin.chatapp/com.example.admin.chatapp.SocketActivity}: android.view.InflateException:二進制XML文件行#9:二進制XML 文件行#9:錯誤充氣類片段 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2728) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2814) 在android.app.ActivityThread 。-wrap12(ActivityThread.java) at android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1527) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6290) at java .lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit 。java:776) 引起:android.view.InflateException:二進制XML文件行#9: 二進制XML文件行#9:錯誤擴展類片段 引起:android.view.InflateException:二進制XML文件行#9:在索引0在方案名稱 非法字符: 錯誤充氣類片段 引起:了java.lang.RuntimeException:java.net.URISyntaxException。http://01e42de0.ngrok.io 在com.example.admin.chatapp.ChatFragment(ChatFragment.java:64 ) at java.lang.Class.newInstance(Native Method) at android.app.Fragment.instantiate(Fragment.java:622) a噸android.app.Fragment.instantiate(Fragment.java:593) 在 android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2302) 在 android.app.FragmentController.onCreateView(FragmentController.java:98) 在android.app.Activity.onCreateView(Activity.java:5982) 在 android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:36) 在 android.support.v4.app.FragmentActivity.onCreateView (FragmentActivity.java:79) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:777) 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727) 在android.view.LayoutInflater.rInflate(LayoutInflater.java:858) 在 android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 在android.view.LayoutInflater.inflate(LayoutInflater.java:518) 在android.view.LayoutInflater.inflate(LayoutInflater.java:426) 在android.view.LayoutInflater.inflate(LayoutInflater.java:377) 在 android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:292) 在 android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 在 com.example.admin.chatapp.SocketActivity.onCreate(SocketActivity.java:22) 在android.app.Activity.performCreate (Activity.java:6760) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1134) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2681) 在 android.app.ActivityThread。 handleLaunchActivity(ActivityThread.java:2814) at android.app.ActivityThread.-wrap12(ActivityThread.java) 在 android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1527) 在android.os.Handler.dispatchMessage(Handler.java:102) 在android.os.Looper.loop(Looper.java:154 ) 在android.app.ActivityThread.main(ActivityThread.java:6290) 在java.lang.reflect.Method.invoke(本機方法) 在 com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit .java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 由java.net引起。的URISyntaxException:http://01e42de0.ngrok.io 在java.net.URI中的$ Parser.fail(URI.java:2856) 在java.net.URI中的$ Parser.checkChars(URI.java:3029) :在索引0在計劃 名非法字符(java.net.URI)$ Parser.checkChar(URI.java:3039) at java.net.URI $ Parser.parse(URI.java:3055) at java.net.URI。(URI.java:590) (IO.java:41) at io.socket.client.IO.socket(IO.java:37) at com.example.admin.chatapp.ChatFragment。(ChatFragment .java:61) at java.lang.Class.newInstance(Native M ethod) 在android.app.Fragment.instantiate(Fragment.java:622) 在android.app.Fragment.instantiate(Fragment.java:593) 在 android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2302 ) 在 android.app.FragmentController.onCreateView(FragmentController.java:98) 在android.app.Activity.onCreateView(Activity.java:5982) 在 android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb .java:36) at android.support.v4.app.FragmentActivity.onCreateView(Fragme ntActivity.java:79) 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:777) 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727) 在android.view.LayoutInflater.rInflate( LayoutInflater.java:858) 在 android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 在android.view.LayoutInflater.inflate(LayoutInflater.java:518) 在android.view.LayoutInflater.inflate(LayoutInflater .java:426) at android.view.LayoutInflater.inflate(LayoutInflater.java:377) 在 android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:292) 在 android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 在 com.example.admin .chatapp.SocketActivity.onCreate(SocketActivity.java:22) 在android.app.Activity.performCreate(Activity.java:6760) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1134) 在 機器人.app.ActivityThread.performLaunchActivity(ActivityThread.java:2681) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2814) 在android.app.ActivityThread.-wrap12(ActivityThread.java) 在 android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1527) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6290) at java .lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:886) 在com。android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

+0

是該URL通過'http://192.168.1.9:3000'可見的Android設備? –

+0

@MarcosPlacona我該怎麼做? –

+0

進入你的android設備的網絡/ wifi設置,看看你的IP地址是 –

回答

0

通過問你關於你自己問題的問題,我想我知道你的問題是什麼。好像你的android設備可能與你的應用程序不在同一個網絡上,並且因爲你在192.168.x.x上運行這個,我很確定這是你的問題所在。

您的Android設備無法看到您的套接字應用程序,因爲它只是在本地主機上運行。

爲了使您的Android設備可以訪問它,您可以使用隧道應用程序,如ngrok。這將使您的應用程序可用。獲取您的計算機上安裝,並在新的終端窗口,如下所示運行:

ngrok http 3000

上然後你會得到一個UR該終端窗口:這是從外部訪問。複製該網址。

樣本here由於圖片上傳看起來已經破裂。

更改這行代碼:

socket = IO.socket("http://192.168.1.9:3000");

您ngrok URL。即

socket = IO.socket("http://fa9910Hf.ngrok.io");

,再試一次,希望你應該看到的消息在未來

+0

你不需要局域網中的Ngrok –

+0

如果兩個設備都在同一網絡。他的回答表明情況並非一定如此。 –

+0

該評論只是一個問題,「如何檢查該端口是否可訪問」。這不是一個網站,所以它不像你可以打開瀏覽器 –

相關問題