1

いくつかの異なるアプリのすべてのクライアントサーバー通信を処理するリモートサービスを作成しようとしています。主なアイデアは、主なアクティビティからサービスを開始し、サーバーへの通信ソケットを開くことです。その後、ソケットは他のアプリで使用されます-そのため、リモートサービスを使用したいと思います...

ソケット接続に問題があり、デバイスで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を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ログオンは次のとおりです。

pid = 20210 11-06 12:13:45.240:I / ActivityManager(392):proc com.mainlauncher:remote for service com.mainlauncher / .ConnectionRemoteService:pid = 20210 uid = 10080 gids = {3003}11-0612を開始します:13:45.300:D / ConnSrv_Debug(392):20210/10080までにmDefaultProxynullを取得11-0612: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:スレッドがキャッチされない例外で終了します(group = 0x40a6b228)11-06 12:13:45.320:E / EmbeddedLogger(392):アプリがクラッシュしました!プロセス:com.mainlauncher:remote 11-06 12:13:45.320:E / EmbeddedLogger(392):アプリがクラッシュしました!パッケージ:com。

この行で例外が発生します:

socket = new Socket(SERVERADDRESS,SERVERPORT);

私はその例外を作ることができるいくつかのことを知っています:1。私<uses-permission android:name="android.permission.INTERNET" />は私のメインマニフェストで使用します。2.サービスは、メインのアクティビティスレッドではなく、分離されたスレッドで実行されます。3.ファイアウォールなどはありません...4。サーバーとの接続をすでに確認しました(サービスがなくてもすべて正常に機能しました)。5.マニフェストでもandroid:process = ":remote"を使用しています。

その例外が発生する理由はありますか?詳細を取得するためにデバッグするにはどうすればよいですか?

OS 2.3を使用してAVDで検索できたので、メインアクティビティスレッドの例外があると思いますが、理由がわかりません。

ありがとう、Lioz。

4

2 に答える 2

2

open()から呼び出していonCreate()ます。onCreate()メインスレッドで呼び出されます。メインスレッドでネットワークI/Oを実行しないでください。別のスレッドが間違った場所にあります。あなたのアクティビティでは、呼び出しbindService()てから永久にループする別のスレッドを開始しています(CPUサイクルをかみ砕く無限ループ、良いことではありません)。は非同期でbindService()あるため、別のスレッド内から呼び出す必要はありません。バインディングを開始bindService()するだけで、バインディングが完了するのを実際には待機しません。これはメインスレッドで実行できます。

スレッドを開始する必要がある場所は、サービス内です。サービスが作成されたら、で別のスレッドを開始するonCreate()必要があり、その別のスレッドがネットワークI / Oを実行する必要があります(つまり、ソケットを開く、読み取り、書き込みなど)。

android:process=":remote"また、マニフェストから削除することで、デバッグを容易にすることができます。これにより、サービスメソッドでブレークポイントを簡単に設定できるようになります。

于 2012-11-06T10:15:33.637 に答える
0

AndroidManifest.xmlにインターネット許可を入れようとしましたか?サーバー(「ローカル」で実行されているサーバーでさえ)に接続するには、インターネットのアクセス許可が必要だと思います。

于 2012-11-05T21:24:56.020 に答える