BindService中使用bindService()方法来绑定服务,调用者和绑定者绑在一起,调用者一旦退出服务也就终止了。
生命周期【onCreate()->onBind()->onUnbind()->onDestroy()】
由于Android 中的Service使用了onBind 的方法去绑定服务,返回一个Ibinder对象进行操作,而我们要获取具体的Service方法的内容的时候,我们需要Ibinder对象返回具体的Service对象才能操作,所以说具体的Service对象必须首先实现Binder对象,这个样子的话我们才能利用bindService的方法对Service进行绑定,获取Binder对象之后获取具体的Service对象,然后才获取Service中的方法等等。所以我们需要注意的是bindService的方式去绑定服务获取的必定是实现了Binder的对象,所以这是我们必须使用Binder的方式去获取Service的方式而不是直接使用Service的类,这个是Android内部实现所约束的。
绑定的过程函数调用的顺序是这样的:
Intent intent = new Intent(MainActivity.this,BindService.class) ->新建了BindService对象->新建了MyBinder对象->bindService(intent, conn, Context.BIND_AUTO_CREATE)->系统回调oncteate()和onBind()->onBind()函数返回MyBinder对象->传递MyBinder对象到onServiceConnected()-> 通过传递的Binder对象获取刚刚和Binder对象对应的BindService 对象 ->调用Service中定义的方法。
有时在Activity函数中想要循环更新UI界面,需要开启一个线程,在线程中更新界面,但又有一个问题是线程中许多控件不能更新(ProsessBar除外),说以需要用到Handler对象,将更新界面的语句写在runnable中,用Handler对象的post方法发送到消息队列中。这是服务于Activity通信的方法之一,但是比较被动。
另一种是使用回调的方法,主动提示Activity更新界面。
现将代码全部写出
Main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lightcontroldemo.MainActivity"
tools:ignore="MergeRootFrame" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="被动查询"
android:textSize="@dimen/abc_action_bar_progress_bar_size" />
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/abc_action_bar_progress_bar_size"
android:gravity="center_horizontal"
android:text="主动通知" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="bind"
android:text="显示时间" />
</LinearLayout>
MainActivity.java
package com.example.lightcontroldemo;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Build;
public class MainActivity extends ActionBarActivity {
private LightService myService;
private TextView tt;
private TextView tt2;
private Handler myHandler;
private static Date dd;
private Runnable run=new Runnable(){
@SuppressLint("SimpleDateFormat")
@Override
public void run() {
// // TODO Auto-generated method stub
SimpleDateFormat sdf=new SimpleDateFormat("hh:mm:ss");
tt.setText(sdf.format(dd));
}
};
private Runnable run2=new Runnable(){
@SuppressLint("SimpleDateFormat")
@Override
public void run() {
// // TODO Auto-generated method stub
SimpleDateFormat sdf=new SimpleDateFormat("hh:mm:ss");
tt2.setText(sdf.format(dd));
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tt=(TextView)findViewById(R.id.textView1);
tt2=(TextView)findViewById(R.id.textView2);
myHandler=new Handler();
Intent i=new Intent(MainActivity.this,LightService.class);
bindService(i, conn, Context.BIND_AUTO_CREATE);
//
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void bind(View v){
if(myService==null)
Toast.makeText(MainActivity.this, "null", Toast.LENGTH_SHORT).show();
else
{
Thread the=new Thread(){
public void run() {
while(true){
dd=myService.getDate();
myHandler.post(run);
try {
sleep(1000); //直接调用
} catch (InterruptedException e) {
return;
}
}
}
};
the.start();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private ServiceConnection conn=new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
myService=((LightService.myBinder)service).getService();
myService.SetOnTextViewListener(new TextViewListener() {
@Override
public void onTextView(Date d) {
MainActivity.dd=d;
myHandler.post(run2);
}
});
}
};
}
LightService.java
package com.example.lightcontroldemo;
import java.util.Date;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class LightService extends Service {
private Handler myHandler;
private Date d;
private TextViewListener textviewlistener;
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
myHandler=new Handler();
d=new Date();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d("SER", "SoundDetectService on Bind...");
// myHandler.postDelayed(r, 1000);
Thread th=new Thread(null,r,"r");
th.start();
return new myBinder() ;
}
private Runnable r=new Runnable(){
@Override
public void run() {
while(true)
{
d=new Date();
try {
Thread.sleep(1000); //直接调用
} catch (InterruptedException e) {
return;
}
if(textviewlistener!=null)
textviewlistener.onTextView(d);
}
}
};
public Date getDate(){
return d;
}
public void SetOnTextViewListener(TextViewListener textviewlistener){
this.textviewlistener=textviewlistener;
}
public class myBinder extends Binder{
public LightService getService(){
return LightService.this;
}
}
}
TextViewListener.java
package com.example.lightcontroldemo;
import java.util.Date;
public interface TextViewListener {
public void onTextView(Date d);
}