我正在尝试创建远程服务,该服务将负责几个不同应用的所有客户端 - 服务器通信。 主要思想是从主活动启动服务并打开通信套接字到服务器。 之后,套接字将被其他应用程序使用 - 这就是我为什么要使用远程服务...
现在我有套接字连接的问题,它在我的设备上抛出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。
答案 0 :(得分:2)
您正在open()
致电onCreate()
。在主线程上调用onCreate()
。您不应该在主线程上执行网络I / O.你在错误的地方有单独的线程。在你的活动中,你正在启动一个单独的线程,它调用bindService()
然后永远循环(无限循环咀嚼CPU周期,不是一件好事)。您不需要从单独的线程中调用bindService()
,因为bindService()
是异步的。只有启动绑定,它实际上并不等待绑定完成。这可以在主线程上完成。
您需要在服务中启动线程的位置。当您的服务被创建时,您应该在onCreate()
中启动一个单独的线程,并且该单独的线程需要执行网络I / O(即:打开套接字,读取,写入等)。
此外,您可以通过从清单中删除android:process=":remote"
来简化调试。这将允许您在服务方法中更容易设置断点。
答案 1 :(得分:0)
您是否尝试将Internet权限放入AndroidManifest.xml中? 连接到服务器(甚至是它的本地&#34;正在运行的服务器)我认为需要互联网权限。