android 后台运行服务之创建后台服务篇
来源:互联网 发布:上海python培训机构 编辑:程序博客网 时间:2024/05/21 11:37
除非另行指定,大部分应用程序操作在前台称作为UI 线程的特殊线程中运行。这可能会造成问题,因为长时间运行的操作会影响你的用户界面的响应。这干扰用户交互操作,甚至可能导致系统错误。为了避免这种情况,Android框架提供了一些类,帮助您关闭负载操作放在一个独立运行于后台的线程。最有用的是intentservice。
接下来将描述如下三种操作。
1. 创建一个后台服务这IntentServic类给单个后台线程运行某个操作提供了一个直接了断的结构, 允许它处理长时间运行的操作,不影响用户界面的响应,同时,一个IntentService 也不会被多用户界面生命周期事件的影响,因此它继续运行的情况下,将关闭AsyncTask。
一个IntentService 有一些限制:
- 不能和用户直接交互,为将结果更新UI, 必须发送结果给Activity。
- 工作请求是有序的,如果一个操作正在IntentService中运行
,而且发送另一个请求给IntentService, 这个请求需要等待知道第一个请求操作完成.
- 运行在IntentService中的操作,不能够被中断.
然而,在大多数情况下,Intentservice 是简单的后台操作的首选方法。
如何创建您自己的IntentService子类以及创建请求回调方法onHandleIntent(),最后描述如何在Manifest 文件中定义IntentService。
a。创建一个IntentService
为创建一个IntentService 组件,定义一个继承于IntentService的类, 并且在该类中实现onHandleIntent()方法。
例子如下:
/** * This service pulls RSS content from a web site URL contained in the incoming Intent (see * onHandleIntent()). As it runs, it broadcasts its status using LocalBroadcastManager; any * component that wants to see the status should implement a subclass of BroadcastReceiver and * register to receive broadcast Intents with category = CATEGORY_DEFAULT and action * Constants.BROADCAST_ACTION. * */public class RSSPullService extends IntentService { // Used to write to the system log from this class. public static final String LOG_TAG = "RSSPullService"; // Defines and instantiates an object for handling status updates. private BroadcastNotifier mBroadcaster = new BroadcastNotifier(this); /** * An IntentService must always have a constructor that calls the super constructor. The * string supplied to the super constructor is used to give a name to the IntentService's * background thread. */ public RSSPullService() { super("RSSPullService"); } /** * In an IntentService, onHandleIntent is run on a background thread. As it * runs, it broadcasts its current status using the LocalBroadcastManager. * @param workIntent The Intent that starts the IntentService. This Intent contains the * URL of the web site from which the RSS parser gets data. */ @Override protected void onHandleIntent(Intent workIntent) { // Gets a URL to read from the incoming Intent's "data" value String localUrlString = workIntent.getDataString(); // Creates a projection to use in querying the modification date table in the provider. final String[] dateProjection = new String[] { DataProviderContract.ROW_ID, DataProviderContract.DATA_DATE_COLUMN }; // A URL that's local to this method URL localURL; // A cursor that's local to this method. Cursor cursor = null; /* * A block that tries to connect to the Picasa featured picture URL passed as the "data" * value in the incoming Intent. The block throws exceptions (see the end of the block). */ try { // Convert the incoming data string to a URL. localURL = new URL(localUrlString); /* * Tries to open a connection to the URL. If an IO error occurs, this throws an * IOException */ URLConnection localURLConnection = localURL.openConnection(); // If the connection is an HTTP connection, continue if ((localURLConnection instanceof HttpURLConnection)) { // Broadcasts an Intent indicating that processing has started. mBroadcaster.broadcastIntentWithState(Constants.STATE_ACTION_STARTED); // Casts the connection to a HTTP connection HttpURLConnection localHttpURLConnection = (HttpURLConnection) localURLConnection; // Sets the user agent for this request. localHttpURLConnection.setRequestProperty("User-Agent", Constants.USER_AGENT); /* * Queries the content provider to see if this URL was read previously, and when. * The content provider throws an exception if the URI is invalid. */ cursor = getContentResolver().query( DataProviderContract.DATE_TABLE_CONTENTURI, dateProjection, null, null, null); // Flag to indicate that new metadata was retrieved boolean newMetadataRetrieved; /* * Tests to see if the table contains a modification date for the URL */ if (null != cursor && cursor.moveToFirst()) { // Find the URL's last modified date in the content provider long storedModifiedDate = cursor.getLong(cursor.getColumnIndex( DataProviderContract.DATA_DATE_COLUMN) ) ; /* * If the modified date isn't 0, sets another request property to ensure that * data is only downloaded if it has changed since the last recorded * modification date. Formats the date according to the RFC1123 format. */ if (0 != storedModifiedDate) { localHttpURLConnection.setRequestProperty( "If-Modified-Since", org.apache.http.impl.cookie.DateUtils.formatDate( new Date(storedModifiedDate), org.apache.http.impl.cookie.DateUtils.PATTERN_RFC1123)); } // Marks that new metadata does not need to be retrieved newMetadataRetrieved = false; } else { /* * No modification date was found for the URL, so newmetadata has to be * retrieved. */ newMetadataRetrieved = true; } // Reports that the service is about to connect to the RSS feed mBroadcaster.broadcastIntentWithState(Constants.STATE_ACTION_CONNECTING); // Gets a response code from the RSS server int responseCode = localHttpURLConnection.getResponseCode(); switch (responseCode) { // If the response is OK case HttpStatus.SC_OK: // Gets the last modified data for the URL long lastModifiedDate = localHttpURLConnection.getLastModified(); // Reports that the service is parsing mBroadcaster.broadcastIntentWithState(Constants.STATE_ACTION_PARSING); /* * Instantiates a pull parser and uses it to parse XML from the RSS feed. * The mBroadcaster argument send a broadcaster utility object to the * parser. */ RSSPullParser localPicasaPullParser = new RSSPullParser(); localPicasaPullParser.parseXml( localURLConnection.getInputStream(), mBroadcaster); // Reports that the service is now writing data to the content provider. mBroadcaster.broadcastIntentWithState(Constants.STATE_ACTION_WRITING); // Gets image data from the parser Vector<ContentValues> imageValues = localPicasaPullParser.getImages(); // Stores the number of images int imageVectorSize = imageValues.size(); // Creates one ContentValues for each image ContentValues[] imageValuesArray = new ContentValues[imageVectorSize]; imageValuesArray = imageValues.toArray(imageValuesArray); /* * Stores the image data in the content provider. The content provider * throws an exception if the URI is invalid. */ getContentResolver().bulkInsert( DataProviderContract.PICTUREURL_TABLE_CONTENTURI, imageValuesArray); // Creates another ContentValues for storing date information ContentValues dateValues = new ContentValues(); // Adds the URL's last modified date to the ContentValues dateValues.put(DataProviderContract.DATA_DATE_COLUMN, lastModifiedDate); if (newMetadataRetrieved) { // No previous metadata existed, so insert the data getContentResolver().insert( DataProviderContract.DATE_TABLE_CONTENTURI, dateValues ); } else { // Previous metadata existed, so update it. getContentResolver().update( DataProviderContract.DATE_TABLE_CONTENTURI, dateValues, DataProviderContract.ROW_ID + "=" + cursor.getString(cursor.getColumnIndex( DataProviderContract.ROW_ID)), null); } break; } // Reports that the feed retrieval is complete. mBroadcaster.broadcastIntentWithState(Constants.STATE_ACTION_COMPLETE); } // Handles possible exceptions } catch (MalformedURLException localMalformedURLException) { localMalformedURLException.printStackTrace(); } catch (IOException localIOException) { localIOException.printStackTrace(); } catch (XmlPullParserException localXmlPullParserException) { localXmlPullParserException.printStackTrace(); } finally { // If an exception occurred, close the cursor to prevent memory leaks. if (null != cursor) { cursor.close(); } } }}注意: 这其他常规的Service组件的回调方法, 例如onStartCommand() 是自动被IntentServices调用,在一个IntentService中, 应当避免重载那些回调方法。
b.在Manifest 文件中定义IntentService
一个IntentService 也需要在应用manifest 文件中应该一个入口(entry),使用<service>元素提供这个入口service,<service>元素 是<application>元素的子项。具体定义如下:
<application android:icon="@drawable/icon" android:label="@string/app_name"> ... <!-- Because android:exported is set to "false", the service is only available to this app. --> <service android:name=".RSSPullService" android:exported="false"/> ... <application/>
android:name 指定IntentService 类的名称,注意这<service>元素不包含intent filter,这Activity发送工作请求给intentService使用明确的Intent,因此没有filter的必要,这也意味这仅仅在同一个应用或其他具有相同user ID 的应用才能访问该服务。发送工作请求给后台服务将在下一篇“android 后台运行服务之发送工作请求给后台服务篇”讲述。
- android 后台运行服务之创建后台服务篇
- android 创建后台运行的服务程序
- android 后台运行服务之发送工作请求给后台服务篇
- android 后台运行服务之报告工作状态篇
- Android Service 后台服务之本地服务
- linux后台运行服务
- 创建后台服务
- android 检测后台服务是否运行
- android 后台服务长时间运行---解决方案
- Android判断后台服务(Service)是否运行
- Android后台服务-service
- nohup让后台服务运行
- 后台服务
- 后台服务
- 【Android】Android中判断后台服务是否正在运行
- android判断某服务是否正在后台运行
- android中获取手机后台运行服务的方法
- android运行后台服务的生命周期与使用技巧
- Http Post发送json序列请求(json序列化和反序列化)
- ARC与非ARC混用
- Spring切入点表达式常用写法
- 网络编程基础
- android 之使用任意XML资源文件
- android 后台运行服务之创建后台服务篇
- C#中二进制运算在权限验证的应用
- QT线程(二)---线程同步
- 一体机电脑好不好
- 如何让mysql数据库允许被远程连接访问?就是从其他的电脑连接我的电脑上的mysql
- WSS4J 1.5和1.6中实现WS Security的Merlin配置上的差异以及其它
- STL,ATL,WTL之间的联系和区别
- IE7 下对onclick方法居然不执行
- Java 并发核心编程