【问题标题】:android service - opening socket throws null exceptionandroid服务-打开套接字抛出空异常
【发布时间】:2012-11-05 19:40:34
【问题描述】:

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

现在我的套接字连接有问题,它在我的设备上引发空异常。 它在使用较旧的 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(); 启动线程 t;

我的连接远程服务:

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;

}

}

主清单文件:

<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 日志:

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 11-06 12:13:45.130: D/InputDispatcher(392): 指针 0: id=0, toolType=1, x=66.049042, y=492.196503, pressure=0.233333, size=0.250980, touchMajor=44.054604, touchMinor=44.054604 , toolMajor=4.818472, toolMinor=4.818472, 方向=0.000000 11-06 12:13:45.130: D/InputDispatcher(392): 调度 MotionEvent [action=0] ToCurrentInputTarget: 40f9a6a8 com.mainlauncher/com.mainlauncher.MainLauncherWindow (服务器) 11-06 12:13:45.150: D/PowerManagerService(392): setPowerState: mPowerState=0x3, newState=0x3, noChangeLights=false, reason=3, force=false, mProximitySensorActive=false, mBootCompleted=true, mUseSoftwareAutoBrightness=true (重复:1) 11-06 12:13:45.160: D/PowerManagerService(392): setPowerState: mPowerState=0x3, newState=0x3, noChangeLights=false, reason=2, force=false, mProximitySensorActive=false, mBootCompleted=true, mUseSoftwareAutoBrightness=true 11-06 12:13:45.160: I/PowerManagerService-JNI(392): [稳定性] PowerManagerService_userActivity JNI 将电源键事件传递给 PowerManagerService userActivity() 11-06 12:13:45.160: D/PowerManagerService(392): setTimeoutLocked: now=4210399, timeoutOverride=-1, nextState=0x3, when=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 11-06 12:13:45.190: D/InputDispatcher(392): 指针 0: id=0, toolType=1, x=65.395096, y=492.919250, pressure=0.233333, size=0.219608, touchMajor=38.547779, touchMinor=38.547779 , toolMajor=4.818472, toolMinor=4.818472, 方向=0.000000 11-06 12:13:45.190: D/InputDispatcher(392): 调度 MotionEvent [action=1] ToCurrentInputTarget: 40f9a6a8 com.mainlauncher/com.mainlauncher.MainLauncherWindow (服务器) 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): 叉 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):在 20210/10080 之前获取 mDefaultProxy null 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 ,请求者状态:已完成,RSSI:-83,链接速度:36,频率:2462,网络 ID:1,显式连接:false 11-06 12:13:45.320: D/AndroidRuntime(20210): 关闭虚拟机 11-06 12:13:45.320: W/dalvikvm(20210): threadid=1: 线程以未捕获的异常退出 (group=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): 致命异常: main 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): 在 java.lang.reflect.Method.invokeNative(Native Method) 11-06 12:13:45.320: E/AndroidRuntime(20210): 在 java.lang.reflect.Method.invoke(Method.java:511) 11-06 12:13:45.320: E/AndroidRuntime(20210): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 11-06 12:13:45.320: E/AndroidRuntime(20210): 在 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): 在 com.android.internal.os.LoggingPrintStream.println(LoggingPrintStream.java:298) 11-06 12:13:45.320: E/AndroidRuntime(20210): 在 com.mainlauncher.ConnectionRemoteService.open(ConnectionRemoteService.java:60) 11-06 12:13:45.320: E/AndroidRuntime(20210): 在 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. 我在主清单中使用&lt;uses-permission android:name="android.permission.INTERNET" /&gt;。 2. Service 在单独的线程下运行,而不是在主活动线程上。 3.没有防火墙等... 4. 我已经检查了与服务器的连接(没有服务一切正常)。 5. 我也在清单中使用 android:process=":remote"。

任何想法为什么会发生该异常? 如何调试它以获取更多详细信息?

它在使用 OS 2.3 的 AVD 上有效,所以我认为这是主活动线程异常的问题,但我不知道为什么。

谢谢, 利奥兹。

【问题讨论】:

    标签: android multithreading sockets android-service socketexception


    【解决方案1】:

    您从onCreate() 拨打open()onCreate() 在主线程上被调用。您不应该在主线程上进行网络 I/O。您将单独的线程放在错误的位置。在您的活动中,您正在启动一个单独的线程,该线程调用bindService(),然后永远循环(无限循环会占用 CPU 周期,这不是一件好事)。您不需要从单独的线程内部调用bindService(),因为bindService() 是异步的。它只是启动绑定,实际上并不等待绑定完成。这可以在主线程上完成。

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

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

    【讨论】:

    • 这就是重点,我确定这与主要活动线程问题有关……再次感谢大卫。无限循环仅用于测试(确保线程继续运行)。谢谢:)
    【解决方案2】:

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

    【讨论】:

    • 是的,这是我在问题中写的第一件事,现在我注意到它没有被代码包围,所以它被隐藏了。编辑和修复...还有其他想法吗?
    • 你能发布你的 AndroidManifest.xml 和异常吗?也许是 WiFiManager 崩溃了?要查看完整的异常,请在 Eclipse 中打开调试控制台或启动 DDMS 工具;)
    • 添加了 Manifest 文件,异常发生在 open socket 命令上,我检查了几次,只有这一行导致崩溃...我会尽快更新完整的崩溃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 2023-03-08
    • 2018-01-26
    相关资源
    最近更新 更多