我正在开发一个与树莓派进行通信的应用程序。应用程序通过套接字连接与服务器通信。
我目前能够建立通信并将其保存在服务中。但我的目标是从活动A改为活动B.问题是,我的应用程序在切换活动时会破坏服务。有办法避免这种情况吗?
活动A启动服务,当我启动活动B时,我将其绑定到活动以调用服务类中的方法。但它不是同一个实例。
我怎么能解决这个问题?
代码
ConnectActivity
package com.example.domen.twitchdronev3;
import android.content.Intent;
import android.os.Parcelable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class ConnectActivity extends AppCompatActivity {
private int port = 3000;
private String ip = "localhost";
private Intent serviceIntent, activityIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_connect);
Toast.makeText(getApplicationContext(), "Starte App...", Toast.LENGTH_LONG).show();
activityIntent = new Intent(this, ControllActivity.class);
serviceIntent = new Intent(this, ClientService.class);
serviceIntent.putExtra("ip", ip);
serviceIntent.putExtra("port", port);
Button btnActivity = (Button) findViewById(R.id.changeActivity);
btnActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(serviceIntent);
activityIntent.putExtra("Intent", (Parcelable) serviceIntent);
startActivity(activityIntent);
}
});
}
// destroys the Activity
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getApplicationContext(), "Destroy (ConnectActivity)", Toast.LENGTH_LONG).show();
}
// Activity stopping
@Override
protected void onStop() {
super.onStop();
}
}
ControllActivity
package com.example.domen.twitchdronev3;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class ControllActivity extends AppCompatActivity {
public static final String TAG = "ControllActivity";
private ClientService clientservice;
private Intent serviceIntent;
private boolean isBound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controll);
Bundle extras = getIntent().getExtras();
serviceIntent = extras.getParcelable("Intent");
Button btnDisconnect = (Button) findViewById(R.id.btnDisconnect);
btnDisconnect.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
doBindToService();
}
});
}
// destroys the Activity
@Override
public void onDestroy(){
super.onDestroy();
Toast.makeText(getApplicationContext(), "Destroy (ControllActivity)", Toast.LENGTH_LONG).show();
doUnbindToService();
stopService(serviceIntent);
}
// Functions to BIND and UNBIND the SERVICE
// bind to Service
public void doBindToService(){
if(!isBound) {
Toast.makeText(this, "(doBindToService) Binding...", Toast.LENGTH_LONG).show();
isBound = bindService(serviceIntent, myConnection, Context.BIND_AUTO_CREATE);
}
}
// Unbind to Service
public void doUnbindToService(){
Toast.makeText(this, "(doUnbindToService) Unbinding...", Toast.LENGTH_LONG).show();
unbindService(myConnection);
isBound = false;
}
private ServiceConnection myConnection = new ServiceConnection(){
public static final String TAG = "ConnectActivity";
@Override
public void onServiceConnected(ComponentName className, IBinder service){
Log.i(TAG, "BOUND SERVICE CONNECTED");
clientservice = ((ClientService.ClientBinder) service).getService();
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name){
Log.i(TAG, "BOUND SERVICE DISCONNECTED");
clientservice = null;
isBound = false;
}
};
}
ClientService
package com.example.domen.twitchdronev3;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
/**
* Created by ViTrex on 12.02.2018.
*/
public class ClientService extends Service {
private static final String TAG = "ClientService";
private final IBinder mBinder = new ClientBinder();
private PrintWriter out;
private Socket socket;
private String ip = "";
private int port = 0;
private Thread backgroundThread;
// the class used for the client binder
public class ClientBinder extends Binder {
ClientService getService() {
// returns the instance of ClientService
// so the client can access the public methods
return ClientService.this;
}
}
//SETTER
public void setIP(String ip) {
this.ip = ip;
}
public void setPort(int port) {
this.port = port;
}
//GETTER
public String getIP() {
return this.ip;
}
public int getPort() {
return this.port;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate...");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "onStartCommand", Toast.LENGTH_LONG).show();
if(intent != null){
setIP(intent.getStringExtra("ip"));
setPort(intent.getIntExtra("port", 3000));
}
return START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind called...");
Toast.makeText(this, getIP() + " " + getPort(), Toast.LENGTH_LONG).show();
backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
buildConnection();
}
});
backgroundThread.start();
return mBinder;
}
private void buildConnection() {
Log.i(TAG, "Try to build up a connection ...");
synchronized (this) {
try {
this.socket = new Socket(getIP(), getPort());
this.out = new PrintWriter(this.socket.getOutputStream(), true);
Log.i(TAG, "Connected");
} catch (IOException ioe) {
Log.i(TAG, ioe.getMessage());
this.socket = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Close Service");
Thread dummy = backgroundThread;
backgroundThread = null;
if (dummy != null)
dummy.interrupt();
if (this.socket != null) {
try {
this.out.close();
this.socket.close();
Log.i(TAG, "Close Socket");
} catch (IOException ioe) {
Log.i(TAG, "ERROR: Close Socket");
}
}
}
}
答案 0 :(得分:0)
你说:
活动A启动服务,当我启动活动B时,我绑定 它调用服务类中的方法的活动。但它 不是同一个例子。
service
实例)? pre-API26
,我认为权限在此之后发生了变化,因此可能需要更多代码。请参阅注意在这个答案的最后)。 我会将此代码(请Intent data
设置的Activity A
)添加到您的ClientService.java
:
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
String a_ip = intent.getStringExtra("ip");
int a_port = intent.getIntExtra("port",-1);
Log.i(TAG, "onStartCommand called...with " + "ip:" + a_ip + "and port:"+ a_port);
setIP(a_ip);
setPort(a_port);
return START_NOT_STICKY;//don't you want START_STICKY ?
}
注意:如果您的应用针对API级别26或更高级别,系统会强制执行 除非应用程序限制使用或创建后台服务 本身就在前台。如果应用需要创建前景 服务,应用程序应调用StartForegroundService()。那种方法 创建后台服务,但该方法向系统发出信号 该服务将自己推向前台。一旦 服务已经创建,服务必须调用它的startForeground() 方法在五秒钟内。来自here