I’m trying to create remote service that will take care for all client-server communication for few different apps.
The main idea is starting the service from main activity and open a communication socket to a server.
after that, the socket will be used by other apps – that’s why i want to use remote service for it…
now i have an issue with the socket connection, it throws null exception on my device.
it works fine on AVD using older android version.
here’s some parts of my code:
my main activity:
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){}
}
};
later on i start the Thread t with t.start();
my 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 file:
<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>
here’s DDMS log on “debug” mode as requested:
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): Pointer 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, orientation=0.000000
11-06 12:13:45.130: D/InputDispatcher(392): Dispatch MotionEvent [action=0] ToCurrentInputTarget: 40f9a6a8 com.mainlauncher/com.mainlauncher.MainLauncherWindow (server)
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 (repeat: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): [Stability] PowerManagerService_userActivity JNI pass power key event to 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): Pointer 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, 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): Before fork
11-06 12:13:45.230: D/dalvikvm(20210): Fork pid: 0
11-06 12:13:45.230: D/dalvikvm(20210): Late-enabling CheckJNI
11-06 12:13:45.230: D/dalvikvm(153): Fork pid: 20210
11-06 12:13:45.240: D/Performance(392): AutoProf Starting process { Process=com.mainlauncher:remote, ActivityName=com.mainlauncher/.ConnectionRemoteService}, pid=20210
11-06 12:13:45.240: I/ActivityManager(392): Start proc com.mainlauncher:remote for service com.mainlauncher/.ConnectionRemoteService: pid=20210 uid=10080 gids={3003}
11-06 12:13:45.300: D/ConnSrv_Debug(392): get mDefaultProxy null by 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, Supplicant state: COMPLETED, RSSI: -83, Link speed: 36, Frequency: 2462, Net ID: 1, Explicit connect: false
11-06 12:13:45.320: D/AndroidRuntime(20210): Shutting down VM
11-06 12:13:45.320: W/dalvikvm(20210): threadid=1: thread exiting with uncaught exception (group=0x40a6b228)
11-06 12:13:45.320: E/EmbeddedLogger(392): App crashed! Process: com.mainlauncher:remote
11-06 12:13:45.320: E/EmbeddedLogger(392): App crashed! Package: com.mainlauncher v1 (1.0)
11-06 12:13:45.320: E/AndroidRuntime(20210): FATAL EXCEPTION: main
11-06 12:13:45.320: E/AndroidRuntime(20210): java.lang.RuntimeException: Unable to create service com.mainlauncher.ConnectionRemoteService: java.lang.NullPointerException
11-06 12:13:45.320: E/AndroidRuntime(20210): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2593)
11-06 12:13:45.320: E/AndroidRuntime(20210): at android.app.ActivityThread.access$1600(ActivityThread.java:139)
11-06 12:13:45.320: E/AndroidRuntime(20210): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1326)
11-06 12:13:45.320: E/AndroidRuntime(20210): at android.os.Handler.dispatchMessage(Handler.java:99)
11-06 12:13:45.320: E/AndroidRuntime(20210): at android.os.Looper.loop(Looper.java:156)
11-06 12:13:45.320: E/AndroidRuntime(20210): at 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): Caused by: 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): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2571)
11-06 12:13:45.320: E/AndroidRuntime(20210): … 10 more
11-06 12:13:45.330: E/EmbeddedLogger(392): Application Label: Launcher
I get the exception on this line:
socket = new Socket(SERVERADDRESS,SERVERPORT);
I know few things that can make that exception:
1. I use <uses-permission android:name="android.permission.INTERNET" /> in my main manifest.
2. The Service run under separated thread, not on the main activity thread.
3. There’s no firewall etc…
4. I checked connection with the server already (all worked fine without the service).
5. I’m using android:process=”:remote” in my manifest too.
any ideas why that exception occurs?
how can i debug it to get more details?
it worked find on AVD using OS 2.3, so i think it’s something with the main activity thread exception, but i can’t find out why.
thanks,
Lioz.
You are calling
open()fromonCreate().onCreate()is called on the main thread. You shouldn’t do network I/O on the main thread. You’ve got the separate thread thing in the wrong place. In your activity you’re starting a separate thread that callsbindService()and then loops forever (infinite loop chewing up CPU cycles, not a good thing). You don’t need to callbindService()from inside a separate thread becausebindService()is asynchronous. It only initiates the binding, it doesn’t actually wait for the binding to complete. This can be done on the main thread.Where you need to start a thread is inside your service. When your service gets created, you should start a separate thread in
onCreate()and that separate thread needs to do the network I/O (ie: open socket, read, write, etc.).Also, you can make debugging easier by removing
android:process=":remote"from the manifest. This will allow you to set breakpoints easier in the service methods.