android服务 - 打开套接字抛出null异常

时间:2012-11-05 19:40:35

标签: android multithreading sockets android-service socketexception

我正在尝试创建远程服务,该服务将负责几个不同应用的所有客户端 - 服务器通信。 主要思想是从主活动启动服务并打开通信套接字到服务器。 之后,套接字将被其他应用程序使用 - 这就是我为什么要使用远程服务...

现在我有套接字连接的问题,它在我的设备上抛出null异常。 它使用较旧的Android版本在AVD上工作正常。

这是我的代码的一些部分:

我的主要活动:

final ServiceConnection conn = new ServiceConnection() {
        public void onServiceConnected(ComponentName name, IBinder service) {
            myRemoteService = ConnectionInterface.Stub.asInterface(service);
        }
        public void onServiceDisconnected(ComponentName name) {
            myRemoteService = null;
        }
    };

    final Thread t = new Thread(){
        public void run(){
            bindService(new Intent(getApplicationContext(), ConnectionRemoteService.class),conn,Context.BIND_AUTO_CREATE);
            while(true){}
        }

   };

稍后我用t.start();

启动Thread t

我的ConnectionRemoteService:

package com.mainlauncher;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ResourceBundle;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.os.IBinder;
import android.widget.Toast;

public class ConnectionRemoteService extends Service {

private static final int SERVERPORT = 7777;
private static final String SERVERADDRESS = "192.168.1.106";

private String deviceID;
private Socket socket;
private DataInputStream in;
private DataOutputStream out;

@Override
public void onCreate() {
    super.onCreate();
    WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
    deviceID = wm.getConnectionInfo().getMacAddress();
    Toast.makeText(this, "Service On.", Toast.LENGTH_LONG).show();
    open();
}

@Override
public void onDestroy() {
    Toast.makeText(this, "Service Off.", Toast.LENGTH_LONG).show();
    close();
}

@Override
public IBinder onBind(Intent intent) {
    return myRemoteServiceStub;
}   

private ConnectionInterface.Stub myRemoteServiceStub = new ConnectionInterface.Stub() {

};

void open(){
    try{
        socket = new Socket(SERVERADDRESS,SERVERPORT);
        in = new DataInputStream(socket.getInputStream());
        out = new DataOutputStream(socket.getOutputStream());
        out.writeUTF(deviceID);
    }
    catch(Exception  e){
        System.err.println(e.getMessage());
    }
}

void close(){
    try {
        if(in!=null)
            in.close();
        if(out!=null)
            out.close();
        if(socket!=null)
            socket.close();
    } 
    catch(Exception  e){
        System.err.println(e.getMessage());
    }
    socket=null;

}

}

Main Manifest文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mainlauncher"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="15" />

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

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity android:name=".MainLauncherWindow" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    <service
        android:name=".ConnectionRemoteService"
        android:process=":remote"/>
</application>

此处的DDMS登录&#34; debug&#34;按要求的模式:

  

11-06 12:13:45.130:D / InputDispatcher(392):notifyMotion - eventTime = 4210399491000,deviceId = 6,source = 0x1002,policyFlags = 0x0,action = 0x0,flags = 0x0,metaState = 0x0,buttonState = 0x0,edgeFlags = 0x0,xPrecision = 1.529167,yPrecision = 1.383594,downTime = 4210399491000   12月11日至6日:13:45.130:d / InputDispatcher(392):指针0:ID = 0,Tooltype刀具= 1,X = 66.049042,Y = 492.196503,压力= 0.233333,大小= 0.250980,touchMajor = 44.054604,touchMinor = 44.054604 ,toolMajor = 4.818472,toolMinor = 4.818472,orientation = 0.000000   11-06 12:13:45.130:D / InputDispatcher(392):Dispatch MotionEvent [action = 0] ToCurrentInputTarget:40f9a6a8 com.mainlauncher / com.mainlauncher.MainLauncherWindow(server)   12月11日至6日:13:45.150:d / PowerManagerService(392):的setPowerState:mPowerState = 0x3,newState = 0x3,noChangeLights =假,原因= 3,力=假,mProximitySensorActive =假,mBootCompleted =真,mUseSoftwareAutoBrightness =真(重复:1)   12月11日至6日:13:45.160:d / PowerManagerService(392):的setPowerState:mPowerState = 0x3,newState = 0x3,noChangeLights =假,原因= 2,力=假,mProximitySensorActive =假,mBootCompleted =真,mUseSoftwareAutoBrightness =真   11-06 12:13:45.160:I / PowerManagerService-JNI(392):[稳定性] PowerManagerService_userActivity JNI将电源键事件传递给PowerManagerService userActivity()   12月11日至6日:13:45.160:d / PowerManagerService(392):setTimeoutLocked:现在= 4210399,timeoutOverride = -1,nextState = 0x3,当= 4216399(mKeylightDelay = 6000,mDimDelay = 2147469000,mScreenOffDelay = 7000)   11-06 12:13:45.190:D / InputDispatcher(392):notifyMotion - eventTime = 4210464940000,deviceId = 6,source = 0x1002,policyFlags = 0x0,action = 0x1,flags = 0x0,metaState = 0x0,buttonState = 0x0, edgeFlags = 0x0,xPrecision = 1.529167,yPrecision = 1.383594,downTime = 4210399491000   12月11日至6日:13:45.190:d / InputDispatcher(392):指针0:ID = 0,Tooltype刀具= 1,X = 65.395096,Y = 492.919250,压力= 0.233333,大小= 0.219608,touchMajor = 38.547779,touchMinor = 38.547779 ,toolMajor = 4.818472,toolMinor = 4.818472,orientation = 0.000000   11-06 12:13:45.190:D / InputDispatcher(392):Dispatch MotionEvent [action = 1] ToCurrentInputTarget:40f9a6a8 com.mainlauncher / com.mainlauncher.MainLauncherWindow(server)   11-06 12:13:45.220:D / dalvikvm(153):前叉   11-06 12:13:45.230:D / dalvikvm(20210):叉子pid:0   11-06 12:13:45.230:D / dalvikvm(20210):延迟启用CheckJNI   11-06 12:13:45.230:D / dalvikvm(153):Fork pid:20210   11-06 12:13:45.240:D / Performance(392):AutoProf启动过程{Process = com.mainlauncher:remote,ActivityName = com.mainlauncher / .ConnectionRemoteService},pid = 20210   11-06 12:13:45.240:I / ActivityManager(392):启动proc com.mainlauncher:远程服务com.mainlauncher / .ConnectionRemoteService:pid = 20210 uid = 10080 gids = {3003}   11-06 12:13:45.300:D / ConnSrv_Debug(392):得到mDefaultProxy null 20210/10080   11-06 12:13:45.300:D / WifiStateMachine(392):syncRequestConnectionInfo mWifiInfo = SSID:linksys,BSSID:00:14:bf:e6:13:8f,MAC:18:87:96:88:cd:68 ,请求状态:COMPLETED,RSSI:-83,链接速度:36,频率:2462,网络ID:1,显式连接:false   11-06 12:13:45.320:D / AndroidRuntime(20210):关闭VM   11-06 12:13:45.320:W / dalvikvm(20210):threadid = 1:线程退出时未捕获异常(组= 0x40a6b228)   11-06 12:13:45.320:E / EmbeddedLogger(392):应用程序崩溃了!进程:com.mainlauncher:remote   11-06 12:13:45.320:E / EmbeddedLogger(392):应用程序崩溃了!包装:com.mainlauncher v1(1.0)   11-06 12:13:45.320:E / AndroidRuntime(20210):致命异常:主要   11-06 12:13:45.320:E / AndroidRuntime(20210):java.lang.RuntimeException:无法创建服务com.mainlauncher.ConnectionRemoteService:java.lang.NullPointerException   11-06 12:13:45.320:E / AndroidRuntime(20210):在android.app.ActivityThread.handleCreateService(ActivityThread.java:2593)   11-06 12:13:45.320:E / AndroidRuntime(20210):在android.app.ActivityThread.access $ 1600(ActivityThread.java:139)   11-06 12:13:45.320:E / AndroidRuntime(20210):在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1326)   11-06 12:13:45.320:E / AndroidRuntime(20210):在android.os.Handler.dispatchMessage(Handler.java:99)   11-06 12:13:45.320:E / AndroidRuntime(20210):在android.os.Looper.loop(Looper.java:156)   11-06 12:13:45.320:E / AndroidRuntime(20210):在android.app.ActivityThread.main(ActivityThread.java:5025)   11-06 12:13:45.320:E / AndroidRuntime(20210):at java.lang.reflect.Method.invokeNative(Native Method)   11-06 12:13:45.320:E / AndroidRuntime(20210):at java.lang.reflect.Method.invoke(Method.java:511)   11-06 12:13:45.320:E / AndroidRuntime(20210):at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:784)   11-06 12:13:45.320:E / AndroidRuntime(20210):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)   11-06 12:13:45.320:E / AndroidRuntime(20210):at dalvik.system.NativeStart.main(Native Method)   11-06 12:13:45.320:E / AndroidRuntime(20210):引起:java.lang.NullPointerException   11-06 12:13:45.320:E / AndroidRuntime(20210):at com.android.internal.os.LoggingPrintStream.println(LoggingPrintStream.java:298)   11-06 12:13:45.320:E / AndroidRuntime(20210):at com.mainlauncher.ConnectionRemoteService.open(ConnectionRemoteService.java:60)   11-06 12:13:45.320:E / AndroidRuntime(20210):at com.mainlauncher.ConnectionRemoteService.onCreate(ConnectionRemoteService.java:33)   11-06 12:13:45.320:E / AndroidRuntime(20210):在android.app.ActivityThread.handleCreateService(ActivityThread.java:2571)   11-06 12:13:45.320:E / AndroidRuntime(20210):......还有10个   11-06 12:13:45.330:E / EmbeddedLogger(392):应用标签:启动器

我在这一行得到例外:

socket = new Socket(SERVERADDRESS,SERVERPORT);

我知道几件事可以解决这个问题: 1.我在主清单中使用<uses-permission android:name="android.permission.INTERNET" />。 2.服务在分离的线程下运行,而不是在主活动线程上运行。 3.没有防火墙等...... 我已经检查了与服务器的连接(没有服务,一切正常)。 5.我使用的是android:process =&#34;:remote&#34;在我的清单中。

为什么会发生这种异常的任何想法? 我如何调试它以获得更多细节?

它使用OS 2.3在AVD上找到了,所以我认为它与主要活动线程异常有关,但我无法找到原因。

感谢, Lioz。

2 个答案:

答案 0 :(得分:2)

您正在open()致电onCreate()。在主线程上调用onCreate()。您不应该在主线程上执行网络I / O.你在错误的地方有单独的线程。在你的活动中,你正在启动一个单独的线程,它调用bindService()然后永远循环(无限循环咀嚼CPU周期,不是一件好事)。您不需要从单独的线程中调用bindService(),因为bindService()是异步的。只有启动绑定,它实际上并不等待绑定完成。这可以在主线程上完成。

您需要在服务中启动线程的位置。当您的服务被创建时,您应该在onCreate()中启动一个单独的线程,并且该单独的线程需要执行网络I / O(即:打开套接字,读取,写入等)。

此外,您可以通过从清单中删除android:process=":remote"来简化调试。这将允许您在服务方法中更容易设置断点。

答案 1 :(得分:0)

您是否尝试将Internet权限放入AndroidManifest.xml中? 连接到服务器(甚至是它的本地&#34;正在运行的服务器)我认为需要互联网权限。