Android-сервис - открытие сокета выбрасывает нулевое исключение

1

Я пытаюсь создать удаленный сервис, который будет заботиться обо всех клиент-серверных связях для нескольких разных приложений. Основная идея заключается в том, чтобы начать обслуживание с основного действия и открыть коммуникационный сокет для сервера. после этого сокет будет использоваться другими приложениями - поэтому я хочу использовать удаленный сервис для него...

теперь у меня проблема с соединением сокета, он выдает исключение null на моем устройстве. он отлично работает на AVD, используя более старую версию для Android.

здесь некоторые части моего кода:

моя основная деятельность:

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){}
        }

   };

позже я запустил Thread t с t.start();

мой 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;

}

}

Основной файл манифеста:

<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, давление = 0.233333, размер = 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): 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 (повтор: 1) 11-06 12: 13: 45.160: D/PowerManagerService (392): setPowerState: mPowerState = 0x3, newState = 0x3, no ChangeLights = false, reason = 2, force = false, mProximitySensorActive = false, mBootCompleted = true, mUseSoftwareAutoBrightness = true 11-06 12: 13: 45.160: I/PowerManagerService-JNI (392): [Стабильность] PowerManagerService_userActivity JNI pass power key event в PowerManagerService userActivity() 11-06 12: 13: 45.160: D/PowerManagerService (392): setTimeoutLocked: now = 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 11-06 12: 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, ориентация = 0.000000 11-06 12:13:45. 190: D/InputDispatcher (392): Dispatch 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): 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, частота: 2 462, Net ID: 1, Явное соединение: false 11-06 12: 13: 45.320: D/AndroidRuntime (20210): выключение VM 11-06 12: 13: 45.320: W/dalvikvm (20210): threadid = 1: thread exit with uncaught exception (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): FATAL EXCEPTION: 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): 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): на 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): на 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.invokeNati ve (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): 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 (родной метод) 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): на com.mainlauncher.ConnectionRemoteService.onCreate(ConnectionRemoteService.java:33) 11-06 12: 13: 45.320: E/AndroidRuntime (20210): at android.app.ActivityThread.handle CreateService (ActivityThread.java:2571) 11-06 12: 13: 45.320: E/AndroidRuntime (20210):... 10 далее 11-06 12: 13: 45.330: E/EmbeddedLogger (392): Application Label: Launcher

Я получаю исключение в этой строке:

socket = new Socket(SERVERADDRESS,SERVERPORT);

Я знаю несколько вещей, которые могут сделать это исключение: 1. Я использую <uses-permission android:name="android.permission.INTERNET"/> use <uses-permission android:name="android.permission.INTERNET"/> в своем основном манифесте. 2. Сервис выполняется под разделенной нитью, а не по основному потоку активности. 3. Нет брандмауэра и т.д. 4. Я проверил соединение с сервером уже (все отлично работало без службы). 5. Я использую android: process = ": remote" в моем манифесте тоже.

любые идеи, почему это исключение происходит? как я могу отладить его, чтобы получить более подробную информацию?

он работал на AVD, используя OS 2.3, поэтому я думаю, что это что-то с исключением основного потока активности, но я не могу понять, почему.

спасибо, Лиоз.

Теги:
multithreading
sockets
android-service
socketexception

2 ответа

2
Лучший ответ

Вы вызываете open() из onCreate(). onCreate() вызывается в основном потоке. Вы не должны выполнять сетевой ввод-вывод в основном потоке. У вас есть отдельная нить в неправильном месте. В вашей деятельности вы начинаете отдельный поток, который вызывает bindService() а затем циклически навеки (бесконечный цикл, пережевывающий циклы CPU, не очень хорошо). Вам не нужно вызывать bindService() из отдельного потока, потому что bindService() является асинхронным. Он инициирует только привязку, но на самом деле не ждет завершения связывания. Это можно сделать в основном потоке.

Где вам нужно начать поток, находится внутри вашей службы. Когда ваша служба создается, вы должны начать отдельный поток в onCreate() и отдельный поток должен выполнять сетевой ввод-вывод (то есть: открыть сокет, читать, писать и т.д.).

Кроме того, вы можете облегчить отладку, удалив android:process=":remote" из манифеста. Это позволит вам легко установить точки останова в методах обслуживания.

  • 0
    так что в этом суть, я был уверен, что это что-то с основной темой активности ... спасибо (снова) Дэвид. бесконечный цикл был только для тестирования (убедитесь, что поток продолжает работать). Спасибо :)
0

Вы пытались установить разрешение на использование Интернета в вашем AndroidManifest.xml? Мне кажется, что подключение к серверу (даже его "локальному" серверу) требует разрешения на доступ в Интернет.

  • 0
    да, это было первое, что я написал в своем вопросе, теперь я заметил, что он не был окружен кодом, поэтому он был скрыт. отредактировано и исправлено ... есть еще идеи?
  • 0
    Вы можете опубликовать свой AndroidManifest.xml и Исключение, пожалуйста? Может быть, это сбой WiFiManager? Чтобы увидеть полное исключение, откройте консоль отладки в Eclipse или запустите инструмент DDMS;)
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню