Service知识点总结

转载请注明出处:http://blog.csdn.net/krislight/article


        Service可以看作一个后台服务,但并非是开启另外的线程,Service还是在主线程中运行.所以需避免耗时操作。

        如果Service還未啟動,調用startService方法會call Service的onCreate()方法,如果已經啟動會call Service的

onStartCommand()方法,在onStartCommand()方法最後會返回一個int值代表Service重啟后的行為,該int值含義有

以下幾種:

Table 1. Restart options

Option

Description

Service.START_STICKY

Service is restarted if it gets terminated. Intent data passed to the onStartCommand method is null. Used for services which manages their own state and do not depend on the Intent data.

Service.START_NOT_STICKY

Service is not restarted. Used for services which are periodically triggered anyway. The service is only restarted if the runtime has pending startService() calls since the service termination.

Service.START_REDELIVER_INTENT

Similar to Service.START_STICKY but the original Intent is re-delivered to the onStartCommand method.

 

通過Intent.getFlags()方法可以判斷Service是否重啟過,返回START_FLAG_REDELIVERYSTART_FLAG_RETRY代表Service已經重啟過了。

通過stopService()stopSelf()來停止Service

如果一個Activity想和Service之間交互通信,使用bindService()來啟動Service

可以指定android:process屬性將service運行到另一個單獨的進程,如果屬性前面有分號如

android:process =”:remote”代表該Service針對自身的應用程序私有,如果沒有分號如

android:process =”remote”代表該Service是共享進程,可以被其他應用程序使用。

很少指定Service運行在單獨運行在自己的進程,除非你希望將Service與其他應用程序共享。


IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,

对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的

worker thread中处理,不会阻塞应用程序的主线程.

使用IntentService下載文件實例:

①在Acitivity中啟動Service

      

public class DownloadService extends IntentService {
  private int result = Activity.RESULT_CANCELED;
  public static final String URL = "urlpath";
  public static final String FILENAME = "filename";
  public static final String FILEPATH = "filepath";
  public static final String RESULT = "result";
  public static final String NOTIFICATION = "com.example.android.service.receiver";

  public DownloadService() {
    super("DownloadService");
  }

  // will be called asynchronously by Android
  @Override
  protected void onHandleIntent(Intent intent) {
    String urlPath = intent.getStringExtra(URL);
    String fileName = intent.getStringExtra(FILENAME);
    File output = new File(Environment.getExternalStorageDirectory(),
        fileName);
    if (output.exists()) {
      output.delete();
    }

    InputStream stream = null;
    FileOutputStream fos = null;
    try {

      URL url = new URL(urlPath);
      stream = url.openConnection().getInputStream();
      InputStreamReader reader = new InputStreamReader(stream);
      fos = new FileOutputStream(output.getPath());
      int next = -1;
      while ((next = reader.read()) != -1) {
        fos.write(next);
      }
      // successfully finished
      result = Activity.RESULT_OK;

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (stream != null) {
        try {
          stream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if (fos != null) {
        try {
          fos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    publishResults(output.getAbsolutePath(), result);
  }

  private void publishResults(String outputPath, int result) {
    Intent intent = new Intent(NOTIFICATION);
    intent.putExtra(FILEPATH, outputPath);
    intent.putExtra(RESULT, result);
    sendBroadcast(intent);
  }
}
在XML配置文件中申請權限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

註冊Service

<service android:name="com.example.android.service.DownloadService" ></service>

佈局文件main_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Download" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Status: " />
        <TextView
            android:id="@+id/status"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Not started" />
    </LinearLayout>
</LinearLayout> 

主頁面:

public class MainActivity extends Activity {
  private TextView textView;
  private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      Bundle bundle = intent.getExtras();
      if (bundle != null) {
        String string = bundle.getString(DownloadService.FILEPATH);
        int resultCode = bundle.getInt(DownloadService.RESULT);
        if (resultCode == RESULT_OK) {
          Toast.makeText(MainActivity.this,
              "Download complete. Download URI: " + string,
              Toast.LENGTH_LONG).show();
          textView.setText("Download done");
        } else {
          Toast.makeText(MainActivity.this, "Download failed",
              Toast.LENGTH_LONG).show();
          textView.setText("Download failed");
        }
      }
    }
  };

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.status);
  }

  @Override
  protected void onResume() {
    super.onResume();
    registerReceiver(receiver, new IntentFilter(DownloadService.NOTIFICATION));
  }
  @Override
  protected void onPause() {
    super.onPause();
    unregisterReceiver(receiver);
  }

  public void onClick(View view) {
    Intent intent = new Intent(this, DownloadService.class);
    // add infos for the service which file to download and where to store
    intent.putExtra(DownloadService.FILENAME, "index.html");
    intent.putExtra(DownloadService.URL,
        "http://www.baidu.com/index.html");
    startService(intent);
    textView.setText("Service started");
  }
}

這裡Activity與Service交互是通過Activity註冊一個BroadCastReceiver來監聽廣播,啟動Service后,一旦Service完成任務發送廣播,BroadCastReceiver監聽到廣播進行相應的處理。


再介紹一個例子讓Activity綁定到運作中的Service,這個Service在開機后自動運行,并模擬抓取數據

先建一個Service:

    
public class LocalWordService extends Service {
  private final IBinder mBinder = new MyBinder();
  private ArrayList<String> list = new ArrayList<String>();
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    Random random = new Random();
    if (random.nextBoolean()) {
      list.add("Linux");
    }
    if (random.nextBoolean()) {
      list.add("Android");
    }
    if (random.nextBoolean()) {
      list.add("iPhone");
    }
    if (random.nextBoolean()) {
      list.add("Windows7");
    }
    if (list.size() >= 20) {
      list.remove(0);
    }
    return Service.START_NOT_STICKY;
  }
  @Override
  public IBinder onBind(Intent arg0) {
    return mBinder;
  }
  public class MyBinder extends Binder {
    LocalWordService getService() {
      return LocalWordService.this;
    }
  }
  public List<String> getWordList() {
    return list;
  }
}
建立一個監聽開機啟動的廣播接收器,該接收器每隔30秒發送啟動Service的廣播: 

public class MyScheduleReceiver extends BroadcastReceiver {
  // restart service every 30 seconds
  private static final long REPEAT_TIME = 1000 * 30;
  @Override
  public void onReceive(Context context, Intent intent) {
    AlarmManager service = (AlarmManager) context
        .getSystemService(Context.ALARM_SERVICE);
    Intent i = new Intent(context, MyStartServiceReceiver.class);
    PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
        PendingIntent.FLAG_CANCEL_CURRENT);
    Calendar cal = Calendar.getInstance();
    // start 30 seconds after boot completed
    cal.add(Calendar.SECOND, 30);
    // fetch every 30 seconds
    // InexactRepeating allows Android to optimize the energy consumption
    service.setInexactRepeating(AlarmManager.RTC_WAKEUP,
        cal.getTimeInMillis(), REPEAT_TIME, pending);
    // service.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
    // REPEAT_TIME, pending);
  }
} 

啟動Service的接收器:

public class MyStartServiceReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    Intent service = new Intent(context, LocalWordService.class);
    context.startService(service);
  }
}

佈局文件mainLayout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Update" > 
    </Button>
    <ListView
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>
</LinearLayout> 

主頁面:

public class MainActivity extends ListActivity {
  private LocalWordService s;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    wordList = new ArrayList<String>();
    adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_list_item_1, android.R.id.text1,
        wordList);
    setListAdapter(adapter);
  }

  @Override
  protected void onResume() {
    super.onResume();
    Intent intent= new Intent(this, LocalWordService.class);
    bindService(intent, mConnection,
        Context.BIND_AUTO_CREATE);
  }

  @Override
  protected void onPause() {
    super.onPause();
    unbindService(mConnection);
  }

  private ServiceConnection mConnection = new ServiceConnection() {

    public void onServiceConnected(ComponentName className, 
        IBinder binder) {
      LocalWordService.MyBinder b = (LocalWordService.MyBinder) binder;
      s = b.getService();
      Toast.makeText(MainActivity.this, "Connected", Toast.LENGTH_SHORT)
          .show();
    }

    public void onServiceDisconnected(ComponentName className) {
      s = null;
    }
  };
  private ArrayAdapter<String> adapter;
  private List<String> wordList;

  public void onClick(View view) {
    if (s != null) {
      Toast.makeText(this, "Number of elements" + s.getWordList().size(),
          Toast.LENGTH_SHORT).show();
      wordList.clear();
      wordList.addAll(s.getWordList());
      adapter.notifyDataSetChanged();
    }
  }
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值