Service

2016-11-01  本文已影响0人  A_Coder

Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要长期运行的任务。

Service生命周期.png

注:

startService()示例:

public class MyService extends Service {  
  
    private static final String TAG = "MyService";  
      
    @Override  
    public void onCreate() {  
        super.onCreate();  
        Log.i(TAG, "onCreate called.");  
    }  
      
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        Log.i(TAG, "onStartCommand called.");  
        return super.onStartCommand(intent, flags, startId);  
    }  
      
    @Override  
    public void onStart(Intent intent, int startId) {  
        super.onStart(intent, startId);  
        Log.i(TAG, "onStart called.");  
    }  
      
    @Override  
    public IBinder onBind(Intent intent) {  
        Log.i(TAG, "onBind called.");  
        return null;  
    }  
      
    @Override  
    public boolean onUnbind(Intent intent) {  
        Log.i(TAG, "onUnbind called.");  
        return super.onUnbind(intent);  
    }  
      
    @Override  
    public void onDestroy() {  
        super.onDestroy();  
        Log.i(TAG, "onDestroy called.");  
    }  
}  

每个Service必须在AndroidManifest.xml中 通过<service>来注册。

<service android:name=".service.MyService" ></service>  

上述代码表示一个在应用包service目录下的继承Service的Myservice服务。

点击事件:

/** 
 * 启动服务按钮方法 
 * @param view 
 */  
public void start(View view) {  
    Intent intent = new Intent(this, MyService.class);  
    startService(intent);  
}  
  
/** 
 * 停止服务按钮方法 
 * @param view 
 */  
public void stop(View view) {  
    Intent intent = new Intent(this, MyService.class);  
    stopService(intent);  
}  

bindService()示例:
因为前面服务中的onBind方法返回值为null,因此,要想实现绑定操作,必须返回一个实现了IBinder接口类型的实例,该接口描述了与远程对象进行交互的抽象协议,有了它我们才能与服务进行交互。

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

返回了一个Binder的实例,而这个Binder恰恰是实现了IBinder接口,这样就可以实现绑定服务的操作了。

public class MainActivity extends AppCompatActivity{  
      
    private static final String TAG = "MainActivity";  
    private boolean binded;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
    }  
      
    private ServiceConnection conn = new ServiceConnection() {  
          
        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
            binded = true;  
            Log.i(TAG, "onServiceConnected called.");  
        }  
          
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
        }  
    };  
      
    /** 
     * 绑定服务 
     * @param view 
     */  
    public void bind(View view) {  
        Intent intent = new Intent(this, MyService.class);  
        bindService(intent, conn, Context.BIND_AUTO_CREATE);  
    }  
      
    /** 
     * 解除绑定 
     * @param view 
     */  
    public void unbind(View view) {  
        unbindService();    
    }  

    //在MainActivity销毁之前如果没有进行解除绑定会导致后台出现异常信息
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        unbindService();  
    } 
      
    /** 
     * 解除服务绑定 
     */  
    private void unbindService() {  
        if (binded) {  
            unbindService(conn);  
            binded = false;  
        }  
    } 
}  

在使用bindService()绑定服务时,我们需要一个ServiceConnection代表与服务的连接,使用bindService()启动服务后调用者和服务绑定到了一起,当调用者被销毁,服务也立即结终止。

public class WeatherService extends Service{
    private static final int NOTIFY_ID = 123;
    
    @Override
    public void onCreate(){
        super.onCreate();
        showNotification();
    }

    //在通知栏显示天气信息
    private void showNotification(){
        NotificationCompat.Builder mBuilder = 
            new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.weather)
                .setContentTitle(getText(R.string.the_day))
                .setContentText(getText(R.string.weather));
        //创建通知被点击时触发的Intent
        Intent resultIntent = new Intent(this, MainActivity.class);
        
        //创建任务栈Builder
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MainActivity.class);
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent = 
            stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(resultPendingIntent);
      
        NotificationManager mNotification = 
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        //构建通知
        final Notification notification = mBuilder.builder();
        //显示通知
        mNotification.notify(NOTIFY_ID, notification);
        //启动前台服务
        startForeground(NOTIFY_ID, notification);
    }
}

使用 startForeground(),如果NOTIFY_ID为 0 ,那么notification将不会显示。
另:
使用Notification通知栏的时候,用TaskStackBuilder来获取PendingIntent处理点击跳转到别的Activity。使用TaskStackBuilder来实现在通知栏中如果有Notification通知的话,点击它,然后会直接跳转到对应的应用程序的某个界面,这时如果按下Back键,会返回到该应用程序的主界面,而不是系统的主界面。addParentStack()是用来添加一个Activity,与这个Activity的AndroidManifest.xml文件中的parentActivityName的属性相关联。

<activity  
    android:name="....."  
    android:parentActivityName=".MainActivity" >  
</activity>  

public class MyService extends Service {  
  
    private static final String TAG = "MyService";  
      
    @Override  
    public IBinder onBind(Intent intent) {  
        Log.i(TAG, "onBind called.");  
        return new MyBinder();  
    }  
      
    /** 
     * 绑定对象 
     * @author user 
     * 
     */  
    public class MyBinder extends Binder {  
          
        /** 
         * 问候 
         * @param name 
         */  
        public void greet(String name) {  
            Log.i(TAG, "hello, " + name);  
        }  
    }  
}  

我们创建了一个MyBinder的内部类,定义了一个greet方法,在onBind方法中就将这个MyBinder的实例返回,只要调用者获取到这个实例,就可以像拿着游戏手柄一样对服务进行操作。

public class MainActivity extends AppCompatActivity{  
      
    /** 
     * 绑定对象实例 
     */  
    private MyService.MyBinder binder;  
    private boolean binded;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
    }  
      
    private ServiceConnection conn = new ServiceConnection() {  
          
        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
            binder = (MyService.MyBinder) service;  //获取其实例  
            binder.greet("coder");                  //调用其方法  
        }  
          
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
        }  
    };  
      
    /** 
     * 绑定服务 
     * @param view 
     */  
    public void bind(View view) {  
        Intent intent = new Intent(this, MyService.class);  
        bindService(intent, conn, Context.BIND_AUTO_CREATE);  
    }  
      
     /** 
     * 解除绑定 
     * @param view 
     */  
    public void unbind(View view) {  
        unbindService();    
    }  

    //在MainActivity销毁之前如果没有进行解除绑定会导致后台出现异常信息
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        unbindService();  
    } 
      
    /** 
     * 解除服务绑定 
     */  
    private void unbindService() {  
        if (binded) {  
            unbindService(conn);  
            binded = false;  
        }  
    } 
}

在绑定服务成功时将IBinder类型的service参数强转为MyService.MyBinder类型,获取绑定中介实例,然后调用其greet方法。绑定服务后,去操作binder对象,也许它还为null,这就容易引起空指针异常,正确的做法是把这些操作放到绑定成功之后。


上一篇 下一篇

猜你喜欢

热点阅读