Android 학습 의 Activity 와 Service 가 통신 하 는 세 가지 방식

14244 단어 자바Android
Activity 와 Service 가 통신 하 는 세 가지 방식
제1 종 단순 통신
Intent 를 통 해 직접 값 을 전달 합 니 다.저 희 는 Service 를 시작 할 때 Intent 의 대상 을 통 해 Service 에 값 을 전달 합 니 다.이런 방식 은 전달 값 이 불편 하고 성능 이 높 지 않 습 니 다.
(1)MainActivity 에서 서비스 시작 과 서비스 종료 단 추 를 통 해 각각 startService(intent)와 stopService(intent)를 호출 하여 서 비 스 를 시작 하고 중지 합 니 다.
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {
    private Intent intent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(MainActivity.this, MyService.class);

        findViewById(R.id.btyStartService).setOnClickListener(this);
        findViewById(R.id.btyStopService).setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btyStartService://    
                intent.putExtra("data", editText.getText().toString());
                startService(intent);
                break;
            case R.id.btyStopService://    
                stopService(intent);
                break;
           
        }
    }
   }

(2)Myservice 에서 저 희 는 onStartCommand(final Intent intent,int flags,intstartId)라 는 함 수 를 통 해 Activity 에서 전 달 된 값 을 받 습 니 다.
Myservice
public class MyService extends Service {
    private Boolean myflags = false;
    private String data = "       ";
    private static final String TAG = "ActivityTest";
    private Callback callback;
    public MyService() {
    }

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

    @Override
    public void onCreate() {
        super.onCreate();
        myflags = true;
        new Thread(){
            @Override
            public void run() {
                super.run();
                while(myflags){
                    try {
                        String str = data;
                        Log.d(TAG, str);
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        Toast.makeText(MyService.this, "   ", Toast.LENGTH_SHORT).show();
                    }
                }
                Log.d(TAG, "      ");
            }

        }.start();
    }

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        data = intent.getStringExtra("data");
        return super.onStartCommand(intent, flags, startId);
    }
}

두 번 째
저희 가 바 인 딩 서 비 스 를 할 때 먼저 해 야 할 일 은 저희 의 MainActivity 가 ServiceConnection 류 를 실현 하도록 하 는 것 입 니 다.이 를 실현 한 후에 저 희 는 ServiceConnection 류 중의 두 가지 방법 인 onServiceConnected 와 onServiceDisconnected 를 다시 써 야 합 니 다.이 두 가지 방법 은 바 인 딩 성공 과 서비스 가 있 는 프로 세 스 가 무 너 질 때 호출 되 는 것 입 니 다.바 인 딩 이 성공 하면...그러면 onServiceConnected(ComponentName componentName,IBinder iBinder)가 실 행 됩 니 다.그리고 두 번 째 매개 변 수 는 바로 MyService 에서 onBind()방법의 반환 값 입 니 다.따라서 이 반환 값 을 통 해 MyService 가 데 이 터 를 전달 할 수 있 습 니 다.
public IBinder onBind(Intent intent) {
        Log.d(TAG, "      ");
       return new Binder();
}

(1)MyService 에서 우 리 는 안 드 로 이 드.os.Binder 류 를 실현 하고 하나의 방법 setData 를 정의 한 다음 에 onBind()방법 으로 대상 을 MainActivity 로 되 돌려 줍 니 다.
public class Binder extends android.os.Binder{
        public void setData(String data){
            MyService.this.data = data;
        }
    }

MyService
public class MyService extends Service {
    private Boolean myflags = false;
    private String data = "       ";
    private static final String TAG = "ActivityTest";
    private Callback callback;
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "      ");
       return new Binder();
    }

    public class Binder extends android.os.Binder{
        public void setData(String data){
            MyService.this.data = data;
        }
    }
    @Override
    public void onCreate() {
        super.onCreate();
        myflags = true;
        new Thread(){
            @Override
            public void run() {
                super.run();
                while(myflags){
                    //System.out.println("      .....");
                    try {
                        String str = data;
                        Log.d(TAG, str);
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        Toast.makeText(MyService.this, "   ", Toast.LENGTH_SHORT).show();
                    }
                }
                Log.d(TAG, "      ");
            }

        }.start();
    }

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        data = intent.getStringExtra("data");
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        myflags = false;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

}

(2)MainActivity 에서 먼저 Binder 대상 을 추가 한 다음 ServiceConnection 에서 MyService 에서 되 돌아 오 는 Binder 대상 을 가 져 옵 니 다.이 어 Binder 대상 을 호출 하 는 방법 setData 를 통 해 데 이 터 를 전달 합 니 다.
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {

    private Intent intent;
    private EditText editText;
    private TextView textView;
    private MyService.Binder myBinder = null;//①

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(MainActivity.this, MyService.class);
        editText = (EditText) findViewById(R.id.editText);
        textView = (TextView) findViewById(R.id.textView);

        findViewById(R.id.btyStartService).setOnClickListener(this);
        findViewById(R.id.btyStopService).setOnClickListener(this);
        findViewById(R.id.btyBindService).setOnClickListener(this);
        findViewById(R.id.btyUnbindService).setOnClickListener(this);
        findViewById(R.id.btySend).setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btyStartService://    
                intent.putExtra("data", editText.getText().toString());
                startService(intent);
                break;
            case R.id.btyStopService://    
                stopService(intent);
                break;
            case R.id.btyBindService://    
                bindService(intent, this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.btyUnbindService://    
                unbindService(this);
                break;
            case R.id.btySend:// MyService    
                if (myBinder != null) {
                    myBinder.setData(editText.getText().toString());//③
                }
                break;
        }
    }
    //             
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        myBinder = (MyService.Binder) iBinder;//②
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {

    }

}

세 번 째,감청 서비스 에서 의 프로 세 스 변화
MyService 에서
(1)공 개 된 인터페이스 추가 Callback
public static interface Callback{
    	void onDataChange(String data);
    }

(2)MyService 내부 에 변 수 를 추가 합 니 다.
private Callback callback;
public void setCallback(Callback callback) {
    this.callback = callback;
}

public Callback getCallback() {
    return callback;
}

(3)외부 에 메 시 지 를 보낸다.
if (callback != null){
    callback.onDataChange(str);
}

(4)Binder 에서 현재 MyService 대상 을 되 돌려 줍 니 다.외부 에서 이벤트 의 바 인 딩 을 추가 할 수 있 습 니 다.
public MyService getMyService(){
    return MyService.this;
}

MyService
public class MyService extends Service {
    private Boolean myflags = false;
    private String data = "       ";
    private static final String TAG = "ActivityTest";
    private Callback callback;
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "      ");
       return new Binder();
    }

    public class Binder extends android.os.Binder{
        public void setData(String data){
            MyService.this.data = data;
        }
        public MyService getMyService(){
            return MyService.this;
        }
    }
    @Override
    public void onCreate() {
        super.onCreate();
        myflags = true;
        new Thread(){
            @Override
            public void run() {
                super.run();
                int i =1;
                while(myflags){
                    //System.out.println("      .....");
                    try {
                        String str = i + ":" +data;
                        Log.d(TAG, str);
                        if (callback != null){
                            callback.onDataChange(str);
                        }
                        sleep(1000);
                        i++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        Toast.makeText(MyService.this, "   ", Toast.LENGTH_SHORT).show();
                    }
                }
                Log.d(TAG, "      ");
            }

        }.start();
    }

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        data = intent.getStringExtra("data");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        myflags = false;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    public void setCallback(Callback callback) {
        this.callback = callback;
    }

    public Callback getCallback() {
        return callback;
    }

    public static interface Callback{
        void onDataChange(String data);
    }
}

MainActivity 에서 저 희 는 onServiceConnected 방법 중의 iBinder 대상 을 통 해 MyService 에서 Callback 의 인 터 페 이 스 를 실현 할 수 있 습 니 다.onDataChange()는 하위 스 레 드 에서 실 행 된 것 이기 때문에 Hander 대상 을 다시 정의 하고 작업 을 하위 스 레 드 에서 메 인 스 레 드 로 전환 하여 메 인 스 레 드 에서 UI 작업 을 하도록 해 야 합 니 다.
//①
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    myBinder = (MyService.Binder) iBinder;
    myBinder.getMyService().setCallback(new MyService.Callback(){
        @Override
        public void onDataChange(String data) {
            Message msg = new Message();
            Bundle b = new Bundle();
            b.putString("data",data);
            msg.setData(b);
            hander.sendMessage(msg);
        }
    });
}

//②
private Handler hander = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        textView.setText(msg.getData().getString("data"));
    }
};

MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {

    private Intent intent;
    private EditText editText;
    private TextView textView;
    private MyService.Binder myBinder = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(MainActivity.this, MyService.class);
        editText = (EditText) findViewById(R.id.editText);
        textView = (TextView) findViewById(R.id.textView);

        findViewById(R.id.btyStartService).setOnClickListener(this);
        findViewById(R.id.btyStopService).setOnClickListener(this);
        findViewById(R.id.btyBindService).setOnClickListener(this);
        findViewById(R.id.btyUnbindService).setOnClickListener(this);
        findViewById(R.id.btySend).setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btyStartService:
                intent.putExtra("data", editText.getText().toString());
                startService(intent);
                break;
            case R.id.btyStopService:
                stopService(intent);
                break;
            case R.id.btyBindService:
                bindService(intent, this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.btyUnbindService:
                unbindService(this);
                break;
            case R.id.btySend:
                if (myBinder != null) {
                    myBinder.setData(editText.getText().toString());
                }
                break;
        }
    }
    //             
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        myBinder = (MyService.Binder) iBinder;
        myBinder.getMyService().setCallback(new MyService.Callback(){
            @Override
            public void onDataChange(String data) {
                Message msg = new Message();
                Bundle b = new Bundle();
                b.putString("data",data);
                msg.setData(b);
                hander.sendMessage(msg);
            }
        });
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
       
    }

    private Handler hander = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            textView.setText(msg.getData().getString("data"));
        }
    };
}

이상 의 코드 에서 버튼 등 컨트롤 은 스스로 추가 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기