- 浏览: 580210 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (338)
- 已过时文章(留念用) (39)
- Android学习笔记 (30)
- Android开发指引自译 (100)
- Android NDK文档自译 (23)
- Android设计指引自译 (2)
- xp(ペケピー)&linux(理奈、铃)酱~ (4)
- ui酱&歌词自译~ (9)
- lua酱~ (9)
- 自我反省 (1)
- 羽game计划 (1)
- XSL酱 (2)
- java酱 (3)
- 设计的领悟 (58)
- 涂鸦作品(pixiv) (1)
- ruby酱 (2)
- Objective-C编程语言自译 (2)
- Android开发月报 (6)
- objc酱 (2)
- photoshop (3)
- js酱 (6)
- cpp酱 (8)
- antlr酱 (7)
- Lua 5.1参考手册自译 (11)
- 收藏品 (3)
- 待宵草计划 (4)
- 体验版截图 (1)
最新评论
-
naruto60:
太给力了!!!!我这网打不开Intel官网,多亏楼主贴了连接, ...
使用HAXM加速的Android x86模拟器(和一些问题) -
yangyile2011:
谢谢博主,翻译得很好哦
【翻译】(4)片段 -
ggwang:
牙痛的彼岸:痹!
牙痛的彼岸 -
ggwang:
总结得很简练清晰啊,学习了!
ANTLR学习笔记一:概念理解 -
leisurelife1990:
mk sdd
用git下载Android自带app的源代码
【翻译】(7)服务
see
http://developer.android.com/guide/topics/fundamentals/services.html
原文见
http://developer.android.com/guide/topics/fundamentals/services.html
-------------------------------
Services
服务
Quickview
快速概览
* A service can run in the background to perform work even while the user is in a different application
* 一个服务可以运行在后台执行工作,即便用户在不同的应用程序中
* A service can allow other components to bind to it, in order to interact with it and perform interprocess communication
* 服务可以允许其它组件绑定到它,以便与它交互并执行进程间通信
* A service runs in the main thread of the application that hosts it, by default
* 默认,服务运行在持有它的应用程序的主线程中
In this document
本文目录
* The Basics 基础
* Declaring a service in the manifest 在清单中声明服务
* Creating a Started Service 创建启动的服务
* Extending the IntentService class 扩展IntentService类
* Extending the Service class 扩展Service
* Starting a service 启动服务
* Stopping a service 停止服务
* Creating a Bound Service 创建绑定服务
* Sending Notifications to the User 向用户发送通知
* Running a Service in the Foreground 在前台运行服务
* Managing the Lifecycle of a Service 管理服务的生命周期
* Implementing the lifecycle callbacks 实现生命周期回调
Key classes
关键类
Service
IntentService
Samples
例子
ServiceStartArguments
LocalService
Articles
文章
* Multitasking the Android Way
* Android的多任务方式
* Service API changes starting with Android 2.0
* 从Android 2.0开始服务API的更改
See also
另见
Bound Services
绑定服务
-------------------------------
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
服务是一种应用程序组件,可以在后台执行长期运行的操作而不提供用户界面。另一个应用组件可以启动一个服务,让它继续在后台执行,即便用户切换到另一个应用程序。额外地,一个组件可以绑定到一个服务以便与之交互,甚至执行进程间通信(IPC)。例如,一个服务可以处理网络事务,播放音乐,执行文件输入输出,或与内容提供者交互,所有这些都来自于后台。
A service can essentially take two forms:
本质上,一个服务可以具有两种形式:
* Started
* 被启动
A service is "started" when an application component (such as an activity) starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. For example, it might download or upload a file over the network. When the operation is done, the service should stop itself.
当一个应用程序组件(诸如一个活动)通过调用startService()启动一个服务时,这个服务处于“被启动”状态。一旦被启动,一个服务可以无限期运行于后台,即便启动它的组件被销毁。通常,一个被启动服务执行一个单一操作,并且不会返回结果给调用方。例如,它可能通过网络下载或上传一个文件。当完成操作时,服务应该停止它自身。
* Bound
* 被绑定
A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
当一个应用程序组件通过调用bindService()绑定到一个服务时,这个服务处于“被绑定”状态。一个被绑定服务提供一个客户端-服务器接口,允许组件与服务交互,发送请求,获取结果,甚至用进程间通信(IPC)跨进程地完成这些事情。一个被绑定服务,仅当另一个应用程序组件绑定到它时,才会运行。多个组件可以立刻绑定到服务,但当它们都解除绑定时,服务就会被销毁。
Although this documentation generally discusses these two types of services separately, your service can work both ways—it can be started (to run indefinitely) and also allow binding. It's simply a matter of whether you implement a couple callback methods: onStartCommand() to allow components to start it and onBind() to allow binding.
虽然本文档普通地分开讨论这两种服务,但是你的服务可以用这两种方式工作。它可以被启动(为了能无限期运行)同时也允许绑定。简单来说,问题是你是否实现一对方法:onStartCommand()允许组件启动它,而onBind()允许绑定。
Regardless of whether your application is started, bound, or both, any application component can use the service (even from a separate application), in the same way that any component can use an activity—by starting it with an Intent. However, you can declare the service as private, in the manifest file, and block access from other applications. This is discussed more in the section about Declaring the service in the manifest.
不管你的应用程序是被启动,被绑定,还是都有,任何应用程序组件都可以用与任意组件使用活动相同的方式使用服务(它甚至可以来自另一个应用程序)——通过用意图来启动它。然而,你可以在清单文件内声明服务为私有的,并拒绝来自其它应用程序的访问。在关于在清单中声明服务的章节中将更详细地讨论这一点。
-------------------------------
Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
警告:一个服务运行在它寄居进程的主线程中——服务不创建它自己的线程,也不运行在单独的进程(除非你指定了)。这意味着,如果你的服务将要做任意CPU密集的工作或阻塞的操作(诸如MP3回放或网络通信),那么你应该在服务内创建一个新线程去做那个工作。通过使用独立线程,你将降低应用程序无响应(ANR)错误的风险,而应用程序的主线程可以保留给你的活动专门用于用户的交互。
-------------------------------
The Basics
基础
-------------------------------
Should you use a service or a thread?
你应该使用服务还是线程?
A service is simply a component that can run in the background even when the user is not interacting with your application. Thus, you should create a service only if that is what you need.
简单来说,一个服务是一种组件,它可以在后台运行,甚至当用户并不和你的应用程序交互时。这样,你应该创建一个服务,仅当那是你所需要的。
If you need to perform work outside your main thread, but only while the user is interacting with your application, then you should probably instead create a new thread and not a service. For example, if you want to play some music, but only while your activity is running, you might create a thread in onCreate(), start running it in onStart(), then stop it in onStop(). Also consider using AsyncTask or HandlerThread, instead of the traditional Thread class. See the Processes and Threading document for more information about threads.
如果你需要在你的主线程外执行工作,但仅当用户正在与你的应用程序交互时,那么你可能应该创建一个新线程而非服务。例如,如果你想播放一些音乐,但仅当你的活动正在运行时才播放,那么你可能在onCreate()创建一个线程,并在onStart()中运行它,然后在onStop()中停止它。另外还应该考虑AsyncTask或HandlerThread,而非传统的Thread类。关于线程的更详细信息请参见进程和线程文档。
Remember that if you do use a service, it still runs in your application's main thread by default, so you should still create a new thread within the service if it performs intensive or blocking operations.
记住如果你使用了服务,它默认仍然运行于你的应用程序的主线程中,所以你仍应该在服务内创建一个新线程,如果它执行密集或阻塞的操作。
-------------------------------
To create a service, you must create a subclass of Service (or one of its existing subclasses). In your implementation, you need to override some callback methods that handle key aspects of the service lifecycle and provide a mechanism for components to bind to the service, if appropriate. The most important callback methods you should override are:
为了创建一个服务,你必须创建Service(或它的其中一个现存子类)的子类。在你的实现中,你需要覆盖一些回调方法,处理服务生命周期的关键方面以及向组件提供一种机制去绑定到服务,如果需要的话。你应该覆盖的最重要回调方法有:
* onStartCommand()
The system calls this method when another component, such as an activity, requests that the service be started, by calling startService(). Once this method executes, the service is started and can run in the background indefinitely. If you implement this, it is your responsibility to stop the service when its work is done, by calling stopSelf() or stopService(). (If you only want to provide binding, you don't need to implement this method.)
当另一个组件,诸如一个活动,通过调用startService()请求启动服务时,系统调用这个方法。一旦这个方法执行,这个服务被启动并可以无限期地运行在后台。如果你实现它,那么你有责任在服务完成时通过调用stopSelf()或stopService()停止它。(如果你只希望提供绑定,那么你不需要实现此方法)
* onBind()
The system calls this method when another component wants to bind with the service (such as to perform RPC), by calling bindService(). In your implementation of this method, you must provide an interface that clients use to communicate with the service, by returning an IBinder. You must always implement this method, but if you don't want to allow binding, then you should return null.
当另一个组件想通过调用bindService()与服务绑定(诸如要执行RPC)(注:RPC是远过程调用的缩写)时系统调用此方法。在你对这个方法的实现中,你必须通过返回一个IBinder对象提供一个接口,让客户端用它与服务通信。你必须总是实现这个方法,但如果你不希望允许绑定,那么你应该返回null。
* onCreate()
The system calls this method when the service is first created, to perform one-time setup procedures (before it calls either onStartCommand() or onBind()). If the service is already running, this method is not called.
当服务首次被创建时系统调用此方法,执行一次性的配置过程(在它调用onStartCommand()或onBind()之前)。如果服务已经运行,那么此方法不被调用。
* onDestroy()
The system calls this method when the service is no longer used and is being destroyed. Your service should implement this to clean up any resources such as threads, registered listeners, receivers, etc. This is the last call the service receives.
当服务不再被使用并正在被销毁时,系统调用此方法。你的服务应该实现它去清除任意资源诸如线程,已注册的监听器,接收器,等等。它是服务接收的最后调用。
If a component starts the service by calling startService() (which results in a call to onStartCommand()), then the service remains running until it stops itself with stopSelf() or another component stops it by calling stopService().
如果一个组件通过调用startService()启动服务(它导致对onStartCommand()的调用),那么服务一直运行直至它用stopSelf()停止自己或另一个组件通过调用stopService()停止它。
If a component calls bindService() to create the service (and onStartCommand() is not called), then the service runs only as long as the component is bound to it. Once the service is unbound from all clients, the system destroys it.
如果一个组件调用bindService()创建服务(并且没有调用onStartCommand()),那么服务仅当组件被绑定到它时才运行。一旦服务从所有客户端中解除绑定,系统会销毁它。
The Android system will force-stop a service only when memory is low and it must recover system resources for the activity that has user focus. If the service is bound to an activity that has user focus, then it's less likely to be killed, and if the service is declared to run in the foreground (discussed later), then it will almost never be killed. Otherwise, if the service was started and is long-running, then the system will lower its position in the list of background tasks over time and the service will become highly susceptible to killing—if your service is started, then you must design it to gracefully handle restarts by the system. If the system kills your service, it restarts it as soon as resources become available again (though this also depends on the value you return from onStartCommand(), as discussed later). For more information about when the system might destroy a service, see the Processes and Threading document.
Android系统将强制停止一个服务,仅当内存过低而它必须回收系统资源供获取用户焦点的活动使用。如果服务被绑定到一个拥有用户焦点的活动,那么它不太可能被杀死,而如果服务被声明为在前台运行(后面会讨论),那么它将几乎从不被杀死。否则,如果服务被启动并长期运行,那么系统将在不久后降低它在后台任务列表中的位置,而服务将变得非常容易被杀死——如果你的服务是被启动的,那么你必须设计它以优雅地处理被系统重启的情况。如果系统杀死你的服务,那么当资源变得再次可用时系统会重启它(虽然这还依赖于你从onStartCommand()中的返回值,正如后面讨论的)。想获取更多关于系统可能何时销毁服务的信息,请参见进程和线程文档。
In the following sections, you'll see how you can create each type of service and how to use it from other application components.
在以下章节中,你将看到你能如何创建每种类型的服务以及如何从其它应用程序组件中使用它。
Declaring a service in the manifest
在清单中声明服务
Like activities (and other components), you must declare all services in your application's manifest file.
如同活动(以及其它组件)那样,你必须在你的应用程序清单文件中声明所有服务。
To declare your service, add a <service> element as a child of the <application> element. For example:
为了声明你的服务,请添加<service>元素作为<application>元素的子元素。例如:
-------------------------------
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
-------------------------------
There are other attributes you can include in the <service> element to define properties such as permissions required to start the service and the process in which the service should run. The android:name attribute is the only required attribute—it specifies the class name of the service. Once you publish your application, you should not change this name, because if you do, you might break some functionality where explicit intents are used to reference your service (read the blog post, Things That Cannot Change).
还有其它属性你可以包含在<service>元素中以定义属性诸如启动服务所需的权限以及服务应该运行在的进程。android:name属性是唯一必要的属性——它指定服务的类名。一旦你发布你的应用程序,你不应改变这个名称,因为如果你这么做,你可能破坏某些功能,而显式的意图用那些功能来引用你的服务(阅读博客文章,不能改变的东西)。
See the <service> element reference for more information about declaring your service in the manifest.
更多关于在清单中声明你的服务的信息,请阅读<service>元素参考手册。
Just like an activity, a service can define intent filters that allow other components to invoke the service using implicit intents. By declaring intent filters, components from any application installed on the user's device can potentially start your service if your service declares an intent filter that matches the intent another application passes to startService().
正像活动那样,一个服务可以定义意图过滤器,允许其它组件使用隐式意图调用服务。通过声明意图过滤器,如果你的服务声明一个意图过滤器而它匹配另一个应用程序传递给startService()的意图,那么来自安装在用户设备上的任意应用程序的组件可以隐式启动你的服务。
If you plan on using your service only locally (other applications do not use it), then you don't need to (and should not) supply any intent filters. Without any intent filters, you must start the service using an intent that explicitly names the service class. More information about starting a service is discussed below.
如果你打算只是私有地使用你的服务(其它应用程序无法使用它),那么你不需要(也不应该)提供任何意图过滤器。如果没有任何意图过滤器,你必须用显式指定服务类名的意图启动服务。更多关于启动服务的信息在后面会讨论。
Additionally, you can ensure that your service is private to your application only if you include the android:exported attribute and set it to "false". This is effective even if your service supplies intent filters.
额外地,你可以确保你的服务对于你的应用程序是私有的,仅当你包含android:exported属性并把它设置为false。即使你的服务提供意图过滤器,这个属性也是有效的。
For more information about creating intent filters for your service, see the Intents and Intent Filters document.
更多关于为你的服务创建意图过滤器的信息,请参见意图和意图过滤器文档。
-------------------------------
Creating a Started Service
创建一个被启动服务
-------------------------------
Targeting Android 1.6 or lower
目标平台是Android 1.6或更低
If you're building an application for Android 1.6 or lower, you need to implement onStart(), instead of onStartCommand() (in Android 2.0, onStart() was deprecated in favor of onStartCommand()).
如果你正在构建Android 1.6或更低的应用程序,你需要实现onStart(),而非onStartCommand()(在Android 2.0中,onStart()被废弃,用onStartCommand()取代)。
For more information about providing compatibility with versions of Android older than 2.0, see the onStartCommand() documentation.
想获取更多关于提供比2.0更旧的Android版本的兼容性,请参见onStartCommand()文档。
-------------------------------
A started service is one that another component starts by calling startService(), resulting in a call to the service's onStartCommand() method.
一个被启动的服务是由另一个组件通过调用startService()启动,导致服务的onStartCommand()方法被调用。
When a service is started, it has a lifecycle that's independent of the component that started it and the service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is done by calling stopSelf(), or another component can stop it by calling stopService().
当服务被启动时,它拥有独立于启动它的组件的生命周期,而且服务可以无限期地运行在后台中,即便启动它的组件已经销毁。因此,要么服务通过调用stopSelf()结束它的工作来停止它自己,要么让另一个组件调用stopService()停止它。
An application component such as an activity can start the service by calling startService() and passing an Intent that specifies the service and includes any data for the service to use. The service receives this Intent in the onStartCommand() method.
一个应用程序组件诸如活动可以通过调用startService()启动服务,传递一个指定服务和包含服务使用数据的意图。服务在onStartCommand()方法中接收这个意图。
For instance, suppose an activity needs to save some data to an online database. The activity can start a companion service and deliver it the data to save by passing an intent to startService(). The service receives the intent in onStartCommand(), connects to the Internet and performs the database transaction. When the transaction is done, the service stops itself and it is destroyed.
例如,假设一个活动需要把一些数据保存到网络数据库。活动可以启动一个协同服务,并通过传递意图给startService(),向它传递要保存的数据。服务在onStartCommand()里接收意图,连接到互联网并执行数据库事务。当事务完成,服务停止它自己并销毁。
-------------------------------
Caution: A services runs in the same process as the application in which it is declared and in the main thread of that application, by default. So, if your service performs intensive or blocking operations while the user interacts with an activity from the same application, the service will slow down activity performance. To avoid impacting application performance, you should start a new thread inside the service.
警告:默认,服务运行在它被声明的应用程序的同一进程中,以及那个应用程序的主线程中。所以,如果在用户与同一应用程序的活动交互时,你的服务执行密集或阻塞操作,那么服务将减慢活动的性能。为了避免对应用程序性能的冲击,你应该在服务中启动一个新线程。
-------------------------------
Traditionally, there are two classes you can extend to create a started service:
传统上,你可以扩展两个类以创建一个被启动的服务:
* Service
This is the base class for all services. When you extend this class, it's important that you create a new thread in which to do all the service's work, because the service uses your application's main thread, by default, which could slow the performance of any activity your application is running.
这是所有服务的基类。当你扩展这个服务时,重要的是你创建一个新线程,在它里面完成所有服务工作,因为默认下,服务使用你的应用程序的主线程,它将减慢你的应用程序正在运行的任意活动的性能。
* IntentService
This is a subclass of Service that uses a worker thread to handle all start requests, one at a time. This is the best option if you don't require that your service handle multiple requests simultaneously. All you need to do is implement onHandleIntent(), which receives the intent for each start request so you can do the background work.
这是Service的子类,它使用工作线程处理所有启动请求,同一时间处理一个。如果你不需要你的服务同时处理多个请求,这是最佳的选择。你需要做的所有事情是实现onHandleIntent(),它接收每个启动请求的意图,使你可以做后台的工作。
The following sections describe how you can implement your service using either one for these classes.
以下章节描述你可以如何用这两个类的其中一个实现你的服务。
Extending the IntentService class
扩展IntentService类
Because most started services don't need to handle multiple requests simultaneously (which can actually be a dangerous multi-threading scenario), it's probably best if you implement your service using the IntentService class.
因为大多数被启动的服务不必同时处理多个请求(这实际上可能是一个危险的多线程场景),所以如果你用IntentService类实现你的服务,这也许是最好的选择。
The IntentService does the following:
IntentService做以下事情:
* Creates a default worker thread that executes all intents delivered to onStartCommand() separate from your application's main thread.
* 创建默认工作者线程,它执行所有传递给onStartCommand()的意图,与你的应用程序的主线程隔离。
* Creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have to worry about multi-threading.
* 创建一个工作队列,它在同一时间传递一个意图到你的onHandleIntent()实现,所以你不必担心多线程。
* Stops the service after all start requests have been handled, so you never have to call stopSelf().
* 在所有启动请求已经被处理后会停止服务,所以你不必调用stopSelf()。
* Provides default implementation of onBind() that returns null.
* 提供onBind()的默认实现,它返回null。
* Provides a default implementation of onStartCommand() that sends the intent to the work queue and then to your onHandleIntent() implementation.
* 提供onStartCommand()的默认实现,它发送意图到工作队列然后发送到你的onHandleIntent()实现。
All this adds up to the fact that all you need to do is implement onHandleIntent() to do the work provided by the client. (Though, you also need to provide a small constructor for the service.)
所有这些事情加在一起看,你需要做的所有事情是实现onHandleIntent()以完成客户端提供的工作。(虽然,你还需要提供服务的小型构造函数)
Here's an example implementation of IntentService:
这里是IntentService的示例实现:
-------------------------------
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
* 构造函数是必需的,并且它必须调用超类的IntentService(String)构造函数,
* 指定工作线程的名称。
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
* IntentService从默认的工作线程中用启动服务的意图调用这个方法。
* 当这个方法返回时,IntentService根据情况停止服务。
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
// 正常情况下我们应该在这里做一些工作,如下载文件。
// 对于我们的例子,我们只要休眠5秒。
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
-------------------------------
That's all you need: a constructor and an implementation of onHandleIntent().
那是你需要做的所有事情:一个构造函数和一个onHandleIntent()实现。
If you decide to also override other callback methods, such as onCreate(), onStartCommand(), or onDestroy(), be sure to call the super implementation, so that the IntentService can properly handle the life of the worker thread.
如果你决定还要覆盖其它回调方法,诸如onCreate(),onStartCommand(),或onDestroy(),那么要确保调用其超类实现,使IntentService可以合理地处理工作者线程的生命(注:生命周期)。
For example, onStartCommand() must return the default implementation (which is how the intent gets delivered to onHandleIntent()):
例如,onStartCommand()必须返回默认实现(它实现了如何把意图传递给onHandleIntent())
-------------------------------
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
-------------------------------
Besides onHandleIntent(), the only method from which you don't need to call the super class is onBind() (but you only need to implement that if your service allows binding).
除了onHandleIntent(),你不需要调用父类的唯一方法是onBind()(但如果你的服务允许绑定,那么你只需要实现它)
In the next section, you'll see how the same kind of service is implemented when extending the base Service class, which is a lot more code, but which might be appropriate if you need to handle simultaneous start requests.
在下面的章节中,你将看到当扩展Service基类时相同种类的服务如何被实现,它需要更多点代码,但如果你需要处理同时发生的启动请求,这可能更合适。
Extending the Service class
扩展Service类
As you saw in the previous section, using IntentService makes your implementation of a started service very simple. If, however, you require your service to perform multi-threading (instead of processing start requests through a work queue), then you can extend the Service class to handle each intent.
正如你在前一个章节看到的,使用IntentService使你对被启动的服务的实现变得非常简单。然而,如果你需要你的服务执行多线程(而非通过工作队列处理启动服务),那么你可以扩展Service类去处理每个意图。
For comparison, the following example code is an implementation of the Service class that performs the exact same work as the example above using IntentService. That is, for each start request, it uses a worker thread to perform the job and processes only one request at a time.
为了方便比较,以下示例代码是Service类实现的示例代码,它执行和上面使用IntentService的例子完全相同的工作。就是说,对于每个启动请求,它使用一个工作者线程执行工作并在同一时间仅处理一个请求。
-------------------------------
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
// 处理来自线程的消息
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
// 正常情况下我们应该在这里做一些工作,如下载文件。
// 对于我们的例子,我们只要休眠5秒。
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
// 使用startId停止服务,
// 使我们不会在处理另一个工作的中途停止服务。
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
// 启动运行服务的线程。
// 注意我们创建独立的线程,因为服务通常运行在进程的主线程(注:从主线程上启动),
// 而我们不希望主线程被阻塞。
// 我们还使它取得后台优先级,使CPU密集的工作不会扰乱我们的用户界面。
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
// 获取HandlerThread的循环器(Looper)并把它应用到我们的处理器(Handler)。
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
// 对于每个启动请求,发送一个消息去启动工作并传递启动ID,
// 这样我们就知道当我们完成工作时,我们正在停止的是哪个请求。
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
// 如果我们被杀死,在从这里返回之后,重新启动。
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
// 我们不提供绑定,所以返回null
return null;
}
@Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
-------------------------------
As you can see, it's a lot more work than using IntentService.
正如你看到的,它需要比使用IntentService更多的工作。
However, because you handle each call to onStartCommand() yourself, you can perform multiple requests simultaneously. That's not what this example does, but if that's what you want, then you can create a new thread for each request and run them right away (instead of waiting for the previous request to finish).
然而,因为你自己处理每个对onStartCommand()的调用,所以你可以同时执行多个请求。这个示例并没有这样做,但如果你想这样做,那么你可以为每个请求创建一个新线程并马上运行它们(而非等待前一个请求处理完)。
Notice that the onStartCommand() method must return an integer. The integer is a value that describes how the system should continue the service in the event that the system kills it (as discussed above, the default implementation for IntentService handles this for you, though you are able to modify it). The return value from onStartCommand() must be one of the following constants:
注意onStartCommand()方法必须返回一个整型。这个整型是一个值,描述系统在系统杀死它的事件中应该如何继续执行服务(正如上面讨论的,IntentService的默认实现为你处理它,但你可以修改它)。onStartCommand()返回值必须是以下常数中的其中一个。
* START_NOT_STICKY
If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.
如果系统在onStartCommand()返回后杀死服务,那么不会重新创建服务,除非有等待的意图要传递。这是最安全的选项,在不必要的时候,以及当你的应用程序可以简单地重启任意未完成工作时,避免运行你的服务。
* START_STICKY
If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand(), but do not redeliver the last intent. Instead, the system calls onStartCommand() with a null intent, unless there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
如果系统在onStartCommand()返回后杀死服务,那么重新创建服务并调用onStartCommand(),但不重新传递最新的意图。取而代之的是,系统用null的意图调用onStartCommand(),除非有等待的意图要启动服务,在该情况下,会传递那些意图。这适合媒体播放器(或类似的服务),它不执行命令,但无限期地运行并等待一个工作。
* START_REDELIVER_INTENT
If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand() with the last intent that was delivered to the service. Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.
如果系统在onStartCommand()返回后杀死服务,那么重新创建服务,并用最近传给服务的意图调用onStartCommand()。任意等待的意图依次被传递。这适合主动地执行应该立刻恢复的工作的服务,诸如下载文件。
For more details about these return values, see the linked reference documentation for each constant.
更多关于这些返回值的细节,请参见每个常量链接的参考文档。
Starting a Service
启动服务
You can start a service from an activity or other application component by passing an Intent (specifying the service to start) to startService(). The Android system calls the service's onStartCommand() method and passes it the Intent. (You should never call onStartCommand() directly.)
你可以通过传递意图(指定要启动的服务)到startService(),从活动或其它应用程序组件中启动一个服务。Android系统调用服务的onStartCommand()方法并把意图传递给它。(你从不应该直接地调用onStartCommand()。)
For example, an activity can start the example service in the previous section (HelloSevice) using an explicit intent with startService():
例如,一个活动可以对startService()使用显式意图启动前面章节中的示例服务(HelloService):
-------------------------------
Intent intent = new Intent(this, HelloService.class);
startService(intent);
-------------------------------
The startService() method returns immediately and the Android system calls the service's onStartCommand() method. If the service is not already running, the system first calls onCreate(), then calls onStartCommand().
startService()方法立刻返回而Android调用服务的onStartCommand()方法。如果服务已不再运行,那么系统首先调用onCreate(),然后调用onStartCommand()。
If the service does not also provide binding, the intent delivered with startService() is the only mode of communication between the application component and the service. However, if you want the service to send a result back, then the client that starts the service can create a PendingIntent for a broadcast (with getBroadcast()) and deliver it to the service in the Intent that starts the service. The service can then use the broadcast to deliver a result.
如果服务也没有提供绑定,那么用startService()传递的意图是应用个程序组件与服务之间唯一的通信模式。然而,如果你希望服务发送结果回来。那么客户端可以启动一个服务,该服务创建获取广播(使用getBroadcast())的PendingIntent并把它传递给启动服务的意图内的服务。然后服务可以使用广播传递结果。
Multiple requests to start the service result in multiple corresponding calls to the service's onStartCommand(). However, only one request to stop the service (with stopSelf() or stopService()) is required to stop it.
启动服务的多请求导致对服务的onStartCommand()方法的多次相应的调用。然而,只有一个停止服务的请求(使用stopSelf()或stopService()),其服务是必须去停止的。
Stopping a service
停止服务
A started service must manage its own lifecycle. That is, the system does not stop or destroy the service unless it must recover system memory and the service continues to run after onStartCommand() returns. So, the service must stop itself by calling stopSelf() or another component can stop it by calling stopService().
一个被启动的服务必须管理它自己的生命周期。就是说,系统不停止或销毁服务,除非它必须回收系统内存而服务在onStartCommand()返回后继续运行。所以服务必须通过调用stopSelf()停止自己或另一组件可以通过调用stopService()停止它。
Once requested to stop with stopSelf() or stopService(), the system destroys the service as soon as possible.
一旦用stopSelf()或stopService()请求停止服务,那么系统尽可能地销毁服务。
However, if your service handles multiple requests to onStartCommand() concurrently, then you shouldn't stop the service when you're done processing a start request, because you might have since received a new start request (stopping at the end of the first request would terminate the second one). To avoid this problem, you can use stopSelf(int) to ensure that your request to stop the service is always based on the most recent start request. That is, when you call stopSelf(int), you pass the ID of the start request (the startId delivered to onStartCommand()) to which your stop request corresponds. Then if the service received a new start request before you were able to call stopSelf(int), then the ID will not match and the service will not stop.
然而,如果你的服务同时处理多个对onStartCommand()的请求,那么当你完成处理一个启动请求时,你不应停止服务,因为你可能曾经接收一个新的启动请求(在首个请求的最后停止,将终止第二个请求)。为了避免这个问题,你可以使用stopSelf(int)确保你的请求停止服务总是基于最近的启动请求。就是说,当你调用stopSelf(int)时,你传递启动请求的ID(传递给onStartCommand()的startId)对应你的停止请求。然后如果在你能调用stopSelf(int)之前服务接收一个新的启动请求,那么该ID将不匹配,而服务将不会停止。
-------------------------------
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand().
警告:重要的是你的应用程序在它完成工作时停止它的服务,避免浪费系统资源和消耗电池电量。如果有必要的话,其它组件可以通过调用stopService()停止服务。即使你绑定了服务,你也必须总是自己停止那个服务,如果它曾经接收到对onStartCommand()的调用。
-------------------------------
For more information about the lifecycle of a service, see the section below about Managing the Lifecycle of a Service.
关于服务生命周期的更多信息,请参见下面关于管理服务生命周期的章节
Creating a Bound Service
创建一个绑定服务
A bound service is one that allows application components to bind to it by calling bindService() in order to create a long-standing connection (and generally does not allow components to start it by calling startService()).
一个被绑定的服务允许应用程序组件通过调用bindService()绑定到它,以创建长期存在的连接(而且通常不允许组件通过调用startService()启动它)。
You should create a bound service when you want to interact with the service from activities and other components in your application or to expose some of your application's functionality to other applications, through interprocess communication (IPC).
你应该在你希望活动和其它应用程序组件与服务交互时,或通过进程间通信(IPC)向其它应用程序公开你的应用程序的某些功能时,创建被绑定的服务。
To create a bound service, you must implement the onBind() callback method to return an IBinder that defines the interface for communication with the service. Other application components can then call bindService() to retrieve the interface and begin calling methods on the service. The service lives only to serve the application component that is bound to it, so when there are no components bound to the service, the system destroys it (you do not need to stop a bound service in the way you must when the service is started through onStartCommand()).
为了创建一个被绑定服务,你必须实现onBind()回调方法以返回一个IBinder,它定义与服务通信的接口。然后,其它应用程序组件可以调用bindService()取出那个接口并开始调用服务上的方法。服务的生存只服务于绑定它的应用程序组件,所以当没有组件绑定到服务时,系统销毁它(你不需要按照一个由onStartCommand()启动的服务的停止方式来停止一个被绑定的服务)
To create a bound service, the first thing you must do is define the interface that specifies how a client can communicate with the service. This interface between the service and a client must be an implementation of IBinder and is what your service must return from the onBind() callback method. Once the client receives the IBinder, it can begin interacting with the service through that interface.
为了创建一个被绑定的服务,你要做的首要工作是定义指定客户端可以如何与服务通信的接口。这个在服务和客户端之间的接口必须是IBinder的实现,并且你的服务从onBind()回调方法中必须返回它。一旦客户端接收到IBinder,你可以通过那个接口开始与服务交互。
Multiple clients can bind to the service at once. When a client is done interacting with the service, it calls unbindService() to unbind. Once there are no clients bound to the service, the system destroys the service.
可以让多个客户端立刻绑定到服务。当一个客户端完成与服务的交互时,它调用unbindService()解除绑定。一旦没有客户端绑定到服务,系统将销毁那个服务。
There are multiple ways to implement a bound service and the implementation is more complicated than a started service, so the bound service discussion appears in a separate document about Bound Services.
有多种方法实现被绑定的服务,而且实现比被启动的服务更复杂,所以被绑定服务放在关于被绑定服务的单独文档中讨论。
-------------------------------
Sending Notifications to the User
向用户发送通知
Once running, a service can notify the user of events using Toast Notifications or Status Bar Notifications.
一旦运行起来,一个服务可以通知事件的用户使用Toast通知或状态栏通知。
A toast notification is a message that appears on the surface of the current window for a moment then disappears, while a status bar notification provides an icon in the status bar with a message, which the user can select in order to take an action (such as start an activity).
toast(注:吐司,烤面包片,可以想象一下吐司机长什么样子的)通知是一种短时间内出现在当前窗口的表面上然后消失的消息,而状态栏通知则是在状态栏提供图标以及一条消息,让用户可以选择以便采取行动(诸如启动活动)。
Usually, a status bar notification is the best technique when some background work has completed (such as a file completed downloading) and the user can now act on it. When the user selects the notification from the expanded view, the notification can start an activity (such as to view the downloaded file).
通常,状态栏通知是在一些后台工作完成(诸如文件下载完)而用户现在可以操作它时最佳的通知技术。当用户在拉下的视图中选择通知时,通知可以启动一个活动(诸如查看已下载的文件)。
See the Toast Notifications or Status Bar Notifications developer guides for more information.
想获取更多信息,请查看Toast通知或状态栏通知的开发者指引。
-------------------------------
Running a Service in the Foreground
在前台运行服务
A foreground service is a service that's considered to be something the user is actively aware of and thus not a candidate for the system to kill when low on memory. A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading, which means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground.
一个前台服务是一种服务,它被认为是用户可主动地意识到的东西,并且不希望让系统在低内存时选择要杀死的东西。一个前台服务必须提供一个通知给状态栏,它被放置在“正在执行”标题下,意味着那个通知不能被忽略,除非服务被停止或从前台中移除。
For example, a music player that plays music from a service should be set to run in the foreground, because the user is explicitly aware of its operation. The notification in the status bar might indicate the current song and allow the user to launch an activity to interact with the music player.
例如,一个来自服务的播放音乐的音乐播放器应该被设置为运行于前台,因为用户明确意识到它的操作。状态栏的通知指示当前音乐并允许用户启动一个活动与音乐播放器交互。
To request that your service run in the foreground, call startForeground(). This method takes two parameters: an integer that uniquely identifies the notification and the Notification for the status bar. For example:
为了请求让你的服务运行于前台,请调用startForeground()。这个方法传入两个参数:一个唯一地标识通知的整型值以及提供给状态栏的Notification(注:通知)对象。
-------------------------------
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION, notification);
-------------------------------
To remove the service from the foreground, call stopForeground(). This method takes a boolean, indicating whether to remove the status bar notification as well. This method does not stop the service. However, if you stop the service while it's still running in the foreground, then the notification is also removed.
为了从前台移除服务,请调用stopForeground()。这个方法传入一个布尔值,指示是否也移除状态栏的通知。这个方法不停止服务。然而,如果当服务正在运行于前台时你停止它,那么通知也会被移除。
-------------------------------
Note: The methods startForeground() and stopForeground() were introduced in Android 2.0 (API Level 5). In order to run your service in the foreground on older versions of the platform, you must use the previous setForeground() method—see the startForeground() documentation for information about how to provide backward compatibility.
注意:方法startForeground()和stopForeground()在Android 2.0(API级别5)中引入。为了在更旧版本平台上的前台运行你的服务,你必须使用以前的setForeground()方法——想获取更多关于提供向后兼容性的信息,请参见startForeground()文档。
-------------------------------
For more information about notifications, see Creating Status Bar Notifications.
想获取更多关于通知的信息,请参见创建状态栏通知。
Managing the Lifecycle of a Service
管理服务的生命周期
The lifecycle of a service is much simpler than that of an activity. However, it's even more important that you pay close attention to how your service is created and destroyed, because a service can run in the background without the user being aware.
服务的生命周期比活动要简单得多。然而,更为重要的是你要十分注意服务是如何被创建和销毁的,因为服务可以运行在后台而不被用户意识。
The service lifecycle—from when it's created to when it's destroyed—can follow two different paths:
服务生命周期——从它被创建开始到它被销毁期间——可以走两种不同的路线:
* A started service
* 一个被启动的服务
The service is created when another component calls startService(). The service then runs indefinitely and must stop itself by calling stopSelf(). Another component can also stop the service by calling stopService(). When the service is stopped, the system destroys it..
当另一个组件调用startService()时服务被创建。然后服务无限期地运行,必须通过调用stopSelf()来停止自己。另一个组件也可以通过stopService()停止该服务。当服务被停止时,系统会销毁它。
* A bound service
* 一个被绑定的服务
The service is created when another component (a client) calls bindService(). The client then communicates with the service through an IBinder interface. The client can close the connection by calling unbindService(). Multiple clients can bind to the same service and when all of them unbind, the system destroys the service. (The service does not need to stop itself.)
当另一个组件(客户端)调用bindService()时服务被创建。然后,客户端通过IBinder接口类与服务通信。客户端可以通过调用unbindService()关闭通信。多个客户端可以绑定到同一个服务,然后当它们都解除绑定时,系统销毁那个服务。(服务不需要停止自己。)
These two paths are not entirely separate. That is, you can bind to a service that was already started with startService(). For example, a background music service could be started by calling startService() with an Intent that identifies the music to play. Later, possibly when the user wants to exercise some control over the player or get information about the current song, an activity can bind to the service by calling bindService(). In cases like this, stopService() or stopSelf() does not actually stop the service until all clients unbind.
这两个路径不是完全隔离的。相反,你可以绑定到一个已经用startService()启动的服务。例如,一个背景音乐服务应该通过传入一个意图调用startService()来启动,那个意图标识要播放的音乐。然后,可能当用户想练习控制播放器或获取当前歌曲的相关信息,那么一个活动可以通过调用bindService()绑定到那个服务。如果出现类似情况,直至客户端解除绑定为止stopService()或stopSelf()都不会真正地停止那个服务。
Implementing the lifecycle callbacks
实现生命周期回调
Like an activity, a service has lifecycle callback methods that you can implement to monitor changes in the service's state and perform work at the appropriate times. The following skeleton service demonstrates each of the lifecycle methods:
类似于活动,一个服务拥有生命周期回调方法,你可以实现它们去监视服务状态的变化并在合适的时候执行工作。下面的框架服务展示每个生命周期方法:
-------------------------------
(图2的内容翻译见下)
Figure 2. The service lifecycle. The diagram on the left shows the lifecycle when the service is created with startService() and the diagram on the right shows the lifecycle when the service is created with bindService().
图2. 服务生命周期。左图演示用startService()创建服务时的生命周期,而右图展示用bindService()创建服务时的生命周期。
-------------------------------
public class ExampleService extends Service {
int mStartMode; // indicates how to behave if the service is killed 指示如果服务被杀死会如何行动
IBinder mBinder; // interface for clients that bind 供绑定客户端使用的接口
boolean mAllowRebind; // indicates whether onRebind should be used 指示onRebind是否应该被使用
@Override
public void onCreate() {
// The service is being created
// 服务正在被创建
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The service is starting, due to a call to startService()
// 服务正在启动,因为调用了startService()
return mStartMode;
}
@Override
public IBinder onBind(Intent intent) {
// A client is binding to the service with bindService()
// 用bindService()把客户端绑定到服务
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// All clients have unbound with unbindService()
// 已经用unbindService()解除所有客户端的绑定
return mAllowRebind;
}
@Override
public void onRebind(Intent intent) {
// A client is binding to the service with bindService(),
// after onUnbind() has already been called
// 用bindService()把一个客户端绑定到服务,
// 在onUnbind()已经被调用后。
}
@Override
public void onDestroy() {
// The service is no longer used and is being destroyed
// 服务不再被使用并正在被销毁
}
}
-------------------------------
Note: Unlike the activity lifecycle callback methods, you are not required to call the superclass implementation of these callback methods.
注意:不像回调生命周期回调方法那样,你不需要调用这些回调方法的超类实现。
-------------------------------
By implementing these methods, you can monitor two nested loops of the service's lifecycle:
通过实现这些方法,你可以监视服务生命周期的两个嵌套循环:
* The entire lifetime of a service happens between the time onCreate() is called and the time onDestroy() returns. Like an activity, a service does its initial setup in onCreate() and releases all remaining resources in onDestroy(). For example, a music playback service could create the thread where the music will be played in onCreate(), then stop the thread in onDestroy().
* 服务的整个生命期发生在onCreate()被调用与onDestroy()返回之间。如同一个活动,服务在onCreate()中完成它的初始化配置而在onDestroy()中释放所有剩余资源。例如,一个音乐回放服务可以在onCreate()里创建播放音乐的线程,然后在onDestroy()里停止该线程。
The onCreate() and onDestroy() methods are called for all services, whether they're created by startService() or bindService().
对于所有服务来说,onCreate()和onDestroy()方法都会被调用,不管它是被startService()还是被bindService()创建。
* The active lifetime of a service begins with a call to either onStartCommand() or onBind(). Each method is handed the Intent that was passed to either startService() or bindService(), respectively.
* 服务的激活生命期始于onStartCommand()和onBind()的调用。每个方法被给予对应传给startService()或bindService()的Intent(注:意图)对象。
If the service is started, the active lifetime ends the same time that the entire lifetime ends (the service is still active even after onStartCommand() returns). If the service is bound, the active lifetime ends when onUnbind() returns.
如果服务被启动,激活生命期与整个生命期同时结束(服务仍是激活的,即便在onStartCommand()返回后)。如果服务被绑定,激活生命期在onUnbind()返回时结束。
-------------------------------
Note: Although a started service is stopped by a call to either stopSelf() or stopService(), there is not a respective callback for the service (there's no onStop() callback). So, unless the service is bound to a client, the system destroys it when the service is stopped—onDestroy() is the only callback received.
注意:虽然调用stopSelf()和stopService()可以停止已启动服务,但对于服务来说没有相应的回调(没有onStop()回调)。所以,除非服务被绑定到一个客户端,否则系统在服务被停止时销毁它——onDestroy()是唯一接收到的回调。
-------------------------------
(图略:
左边 / 右边:
1. 对startService()的调用 / 对bindService()的调用
2. onCreate() / onCreate()
------ 激活的生命期
3. onStartCommand() / onBind()
4. 服务正在运行 / 客户端绑定到服务
5. 服务被自己或一个客户端停止 / 所有客户端通过调用unbindService()解除绑定
6. (无) / onUnbind()
7. onDestroy / onDestroy
-------
8. 服务关闭 / 服务关闭
未被绑定的服务 / 被绑定的服务
)
Figure 2 illustrates the typical callback methods for a service. Although the figure separates services that are created by startService() from those created by bindService(), keep in mind that any service, no matter how it's started, can potentially allow clients to bind to it. So, a service that was initially started with onStartCommand() (by a client calling startService()) can still receive a call to onBind() (when a client calls bindService()).
图2描绘服务的典型回调方法。虽然该图划分startService()创建的服务和bindService()创建的服务,但请记住任何服务,不管它是如何被启动,都可以隐式地允许客户端绑定到它。所以,最初用onStartCommand()启动的服务(通过客户端调用startService())仍可以接收对onBind()的调用(当客户端调用bindService()时)
For more information about creating a service that provides binding, see the Bound Services document, which includes more information about the onRebind() callback method in the section about Managing the Lifecycle of a Bound Service.
更多关于创建提供绑定功能的服务的信息,请参见被绑定的服务的文档,在关于管理被绑定的服务的生命周期的章节中包含更多关于onRebind()回调方法的信息。
Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.
除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。
Android 4.0 r1 - 27 Oct 2011 21:16
Android 4.0 r1 - 29 Mar 2012 18:25
-------------------------------
patch:
1. Android 4.0 r1 - 29 Mar 2012 18:25
图被修改过
-------------------------------
Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
(此页部分内容基于Android开源项目,以及使用根据创作公共2.5来源许可证描述的条款进行修改)
发表评论
-
【翻译】(9-补丁2)电话簿提供者
2012-07-18 12:54 2400【翻译】(9-补丁2)电话簿提供者 see h ... -
【翻译】(8-补丁1)Android接口定义语言(AIDL)
2012-07-02 05:55 2927【翻译】(8-补丁1)Andro ... -
【翻译】(0)应用组件
2012-06-30 23:50 829【翻译】(0)应用组件 see http:// ... -
【翻译】(88)传感器
2012-05-21 21:25 1077【翻译】(88)传感器 ... -
【翻译】(87)复制与粘贴
2012-05-20 14:48 1929【翻译】(87)复制与粘贴 see http: ... -
【翻译】(86)音频捕捉
2012-05-16 15:14 1104【翻译】(86)音频捕捉 ... -
【翻译】(85)照相机
2012-05-13 15:09 3796【翻译】(85)照相机 see http:// ... -
【翻译】(84)JetPlayer
2012-04-21 16:24 981【翻译】(84)JetPlayer see h ... -
【翻译】(83)媒体回放
2012-04-21 16:00 1860【翻译】(83)媒体回放 see http:/ ... -
【翻译】(82)多媒体与照相机
2012-04-18 23:05 953【翻译】(82)多媒体与照相机 see htt ... -
【翻译】(23-补丁3)构建无障碍服务
2012-04-18 21:57 1627【翻译】(23-补丁3)构 ... -
【翻译】(23-补丁2)使应用程序无障碍
2012-04-16 13:08 2099【翻译】(23-补丁2)使应用程序无障碍 see ... -
【翻译】(23-补丁1)无障碍
2012-04-11 22:38 911【翻译】(23-补丁1)无 ... -
【翻译】(81)Renderscript之运行时API参考手册
2012-04-11 22:13 1416【翻译】(81)Renderscript之运行时API参 ... -
【翻译】(80)Renderscript之计算
2012-04-09 14:09 1444【翻译】(80)Renderscript之计算 ... -
【翻译】(79)Renderscript之图形
2012-04-08 13:59 2866【翻译】(79)Renderscript之图形 ... -
【翻译】(78)Renderscript
2012-04-04 15:35 1442【翻译】(78)Renderscript see ... -
【翻译】(77)可绘画对象动画
2012-03-18 10:52 711【翻译】(77)可绘画对象动画 see htt ... -
【翻译】(76)视图动画
2012-03-18 10:04 806【翻译】(76)视图动画 see http:/ ... -
【翻译】(75)属性动画
2012-03-17 18:24 2508【翻译】(75)属性动画 see http:/ ...
相关推荐
sdad
本课程设计是某公司的工资管理系统。在这个计算机快速发展的世界里,计算机为信息处理提供了物美价廉的手段,对于推动我国管理信息处理现代化起到了重要作用。工资管理是一项琐碎、复杂而又十分细致的工作,工资计算、发放、核算的工作量很大,一般不允许出错,如果实行手工操作,每月发放工资须手工填制大量的表格,这就会耗费工作人员大量的时间和精力,计算机进行工资发放工作,不仅能够保证工资核算准确无误、快速输出,而且还可以利用计算机对有关工资的各种信息进行统计,既方便又快捷地完成员工工资的发放。 本课程设计过程中根据设计中的需求及对工资管理系统采用了模块化的设计思想,在机房我们在Windows XP 操作系统环境下,采用 myeclipse7作为开发工具,主要连接 Access 数据库来实现公司的工资管理系统的主要功能。在设计过程中,我们首先小组首先对整体的思路进行分析,然后进行分工。对数据库和类进行设计,实现了工资管理系统的功能。其功能主要包括公司用户管理、人员管理、部门管理、工资管理等功能.。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
基于鸟鸣声识别的鸟类分类系统项目源代码全套技术资料.zip
1、嵌入式物联网单片机项目开发例程,简单、方便、好用,节省开发时间。 2、代码使用IAR软件开发,当前在CC2530上运行,如果是其他型号芯片,请自行移植。 3、软件下载时,请注意接上硬件,并确认烧录器连接正常。 4、有偿指导v:wulianjishu666; 5、如果接入其他传感器,请查看账号发布的其他资料。 6、单片机与模块的接线,在代码当中均有定义,请自行对照。 7、若硬件有差异,请根据自身情况调整代码,程序仅供参考学习。 8、代码有注释说明,请耐心阅读。 9、例程具有一定专业性,非专业人士请谨慎操作。
毕业设计前后端分离博客项目源代码.zip
Eclipse+MySql+JavaSwing选课成绩管理系统,原文博客在https://blog.csdn.net/qq_50062694/article/details/124649345?spm=1001.2014.3001.5502。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。
什么是流程挖掘?为什么需要流程挖掘?流程挖掘面向的部门是哪些?流程挖掘之后做什么?如果想知道这些,请阅读此文。
### Android程序开发初级教程(一):初识Android **平台概述** Google推出的Android操作系统平台已经正式亮相,这是一个基于Linux内核的开源操作系统。对于开发者而言,了解其架构和支持的开发语言至关重要。以下是Android平台的架构概览: **平台架构及功能** 1. **应用框架(Application Framework)**:包含可重用和可替换的组件,确保所有软件在该层面上的平等性。 2. **Dalvik虚拟机(Dalvik Virtual Machine)**:一个基于Linux的虚拟机,为Android应用提供运行环境。 3. **集成浏览器(Integrated Browser)**:基于开源WebKit引擎的浏览器,位于应用层。 4. **优化图形(Optimized Graphics)**:包括自定义的2D图形库和遵循OpenGL ES 1.0标准的3D实现。 5. **SQLite数据库**:用于数据存储。 6. **多媒体支持(Media Support)**:支持通用音频、视频以及多种图片格式(如MPEG4, H.264
项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7
212) Outgrid - 多用途 Elementor WordPress 主题 v2.0.0.zip
weixin138社区互助养老+ssm(论文+源码)_kaic.zip
深圳建筑安装公司“高处作业安全技术操作规程”
【项目简介】 代码主干网络采用Swin-Transformer 家族系列,包括【tiny、small、base】三种模型。pretrained和freeze_layers参数为是否采用官方预训练模型和是否仅训练分类头。为了做对比消融试验,优化器采用了Adam和SGD、AdamW三种。损失函数采用多类别的交叉熵、学习率优化策略采用cos余弦退火算法 【评估网络】 评估的指标采用loss和准确率(accuracy),分别会在训练集和验证集上进行评估、输出、绘制曲线图像。同时会在训练集、验证集进行一系列评估,包含混淆矩阵、recall、precision、F1 score等等曲线图像,以及recall、precision、F1 score、特异度的输出信息等等。 【具体各类别的指标在json文件中查看】 【如果想要更换数据集训练,参考readme文件】 【本项目为8种番茄病害图片(约4k张数据),包含数据集和标签,可以一键运行】
城市公交查询功能描述 城市公交查询系统的主要目的是为市民提供便捷的公交信息查询服务,帮助用户快速获取公交线路、站点、时刻表等信息,从而提高出行效率。以下是该系统可能具备的功能描述: 1. 公交线路查询 线路搜索:用户可以通过输入公交线路编号或线路名称,快速查询到该线路的详细信息。 线路详情:展示所选线路的起点、终点、途经站点、首末班车时间、发车间隔等信息。 线路图展示:提供线路的可视化地图,显示线路走向及各个站点位置。 2. 站点查询 站点搜索:用户可以通过输入站点名称或编号,查询该站点的相关信息。 站点详情:展示所选站点的上下车线路、周边设施、换乘信息等。 实时到站信息:提供该站点即将到达的公交车信息,包括预计到达时间和车牌号。 3. 实时公交信息 实时位置追踪:用户可以查看公交车的实时位置,了解公交车的行驶状态。 到站预测:根据实时数据,预测公交车到达各个站点的时间,帮助用户合理安排出行。 4. 换乘查询 换乘方案推荐:用户输入起点和终点后,系统提供最佳的换乘方案,包括所需的公交线路、换乘站点及步行距离。 换乘时间估算:计算并展示换乘所需的总时间,包括等车时间和步行时间。 5.
交通旅游订票功能描述 交通旅游订票系统是为了简化旅游出行过程,提升用户的预定体验。该系统通常集成了机票、火车票、汽车票、船票、景区门票等多种交通和旅游产品的预订、支付及管理功能。以下是该系统可能具备的功能描述: 1. 用户管理 用户注册与登录:提供游客注册与登录功能,支持邮箱、手机号等多种方式注册,保证用户信息安全。 个人信息管理:用户可以查看和编辑个人信息,如身份证号、联系方式、常用地址等。 乘客信息保存:可保存常用乘客信息,如身份证、护照、儿童票信息,方便快速预定。 2. 交通票务管理 票务查询:提供交通工具的实时查询功能,支持机票、火车票、汽车票、船票等的查询,包含出发时间、到达时间、票价、座位情况等信息。 多种票务类型支持:支持单程票、往返票、联程票、团体票等多种票种,满足不同用户需求。 票价比较:根据日期、交通工具等条件,自动比较票价,帮助用户选择最合适的票务。 票务预订与支付:提供便捷的在线预订和支付功能,支持多种支付方式(如银行卡、支付宝、微信等)。 票务改签与退票:用户可以在线申请改签和退票,并查看相关费用及政策。 3. 旅游产品预订 景点门票预订:用户可以在线选择
企业数据管理系统项目源代码.zip
项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7
基于plc的污水处理,组态王动画仿真,带PLC源代码,组态王源代码,图纸,IO地址分配
SINAMICS S120驱动第三方直线永磁同步电机系列视频_配置和优化.mp4