如何在主线程上运行服务?

Rag*_*sis 9 sockets multithreading android android-service

我正在尝试启动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();
Run Code Online (Sandbox Code Playgroud)

然后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;
}
Run Code Online (Sandbox Code Playgroud)

但是当我打电话给我时,我有错误

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*
Run Code Online (Sandbox Code Playgroud)

我认为问题是,servicemain thread的,但我无法找到我应该如何开始新的(影响无关)线程服务,以保持connection alive

ser*_*nka 13

您可以使用IntentService.只需使用主线程中的Intent正常启动它.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;
    }    
}
Run Code Online (Sandbox Code Playgroud)

在您的活动中,您将按以下方式启动服务.

startService(new Intent(this, MyIntentService.class));
Run Code Online (Sandbox Code Playgroud)

如果您需要持久的服务,您可以创建一个正常的服务并在那里启动一个线程.这是一个例子.确保将其作为"前台"服务启动.这将使服务运行更长时间而不会被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)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Ragaisis你应该更好地使用线程的普通服务.我更新了我的答案.这有帮助吗? (5认同)
  • 但我读到IntentService只用于一次性任务.我应该通过套接字保持连接,向服务器发送一些请求,接收响应并监听服务器命令.这是一项非常困难的长期任务.我可以使用IntentService来实现它吗? (2认同)

Tri*_*mon 5

将此代码移到您的线程中:

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();
}
Run Code Online (Sandbox Code Playgroud)

仅作为示例(我不确定这是否适合您的任务):

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();
Run Code Online (Sandbox Code Playgroud)

您应该知道服务正在UI线程上运行,因此您收到此错误。请访问这个不错的网站,以获取有关Android中各种线程化方法的更多信息。