13

サーバーに接続するために起動serviceしてから開こうとしています。socket

ボタンをクリックすると、新規作成してThreadからサービスを開始します。

Thread t = new Thread(){
        public void run(){
            mIntent= new Intent(MainActivity.this, ConnectonService.class);
            mIntent.putExtra("KEY1", "Value used by the service");
            context.startService(mIntent);
        }
    };
t.start();

次に、サーバーserviceを開いsocketて接続しようとします

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //TODO do something useful


    try {
        InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
        socket = new Socket(serverAddr, SERVERPORT);
        Scanner scanner = new Scanner(socket.getInputStream());
        message = scanner.nextLine();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return Service.START_NOT_STICKY;
}

しかし、私がそれを呼び出すと、エラーが発生します

08-30 08:56:49.268: E/AndroidRuntime(3751): java.lang.RuntimeException: Unable to start service com.example.testofconnection.ConnectonService@40ef02a8 with Intent { cmp=com.example.testofconnection/.ConnectonService (has extras) }: android.os.NetworkOnMainThreadException*

service問題はonだと思いますがmain thread、維持するために新しい(独立した)スレッドでサービスを開始する方法がわかりませんかconnection alive

4

2 に答える 2

20

これには IntentService を使用できます。メインスレッドからのインテントで通常どおり起動するだけです。onHandleIntent()メソッドはバックグラウンド スレッドで実行されます。そこにソケットコードを入れてください。コード例を次に示します。

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // this method is called in background thread
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }    
}

あなたのアクティビティでは、次のようにサービスを開始します。

startService(new Intent(this, MyIntentService.class));

永続的なサービスが必要な場合は、通常のサービスを作成して、そこでスレッドを開始できます。ここに例があります。必ず「フォアグラウンド」サービスとして起動してください。これにより、Android によって強制終了されることなく、サービスをより長く実行できます。

public class MyAsyncService extends Service {

    private AtomicBoolean working = new AtomicBoolean(true)

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while(working.get()) {
                // put your socket-code here
                ...
            }
        }
    }

    @Override
    public void onCreate() {

        // start new thread and you your work there
        new Thread(runnable).start();

        // prepare a notification for user and start service foreground
        Notification notification = ...
        // this will ensure your service won't be killed by Android
        startForeground(R.id.notification, notification);
    }

    @Override
    public onDestroy() {
        working.set(false)
    }
}
于 2013-08-30T06:21:22.787 に答える
6

このコードをスレッドに移動します。

try {
    InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
    socket = new Socket(serverAddr, SERVERPORT);
    Scanner scanner = new Scanner(socket.getInputStream());
    message = scanner.nextLine();
} catch (IOException e) {
    e.printStackTrace();
}

例として(これがあなたの仕事に合っているかどうかはわかりません):

Thread t = new Thread(){
        public void run(){
            try {
                InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
                socket = new Socket(serverAddr, SERVERPORT);
                Scanner scanner = new Scanner(socket.getInputStream());
                message = scanner.nextLine();
            } catch (IOException e) {
                e.printStackTrace();
            }

            mIntent= new Intent(MainActivity.this, ConnectonService.class);
            mIntent.putExtra("KEY1", "Value used by the service");
            context.startService(mIntent);
        }
    };
t.start();

サービスが UI スレッドで実行されていることを知っておく必要があるため、このエラーが発生しました。Android でのさまざまなスレッド化アプローチの詳細については、このすばらしいサイトを確認してください。

于 2013-08-30T06:21:42.077 に答える