【发布时间】:2011-03-18 14:52:27
【问题描述】:
如何在 Android Service 中获取从调用 Activity 传递的数据?
【问题讨论】:
标签: android android-intent android-activity service
如何在 Android Service 中获取从调用 Activity 传递的数据?
【问题讨论】:
标签: android android-intent android-activity service
关于“如何通过意图从 Activity 向服务发送数据”这个问题的准确答案,您是否必须覆盖接收意图对象的 onStartCommand() 方法:
当您创建Service 时,您应该覆盖onStartCommand() 方法,因此如果您仔细查看下面的签名,您会收到传递给它的intent 对象:
public int onStartCommand(Intent intent, int flags, int startId)
因此,您将从活动中创建意图对象以启动服务,然后将数据放入意图对象中,例如,您希望将 UserID 从 Activity 传递到 Service:
Intent serviceIntent = new Intent(YourService.class.getName())
serviceIntent.putExtra("UserID", "123456");
context.startService(serviceIntent);
当服务启动时,其onStartCommand() 方法将被调用,因此在此方法中,您可以从意图对象中检索值(UserID),例如
public int onStartCommand (Intent intent, int flags, int startId) {
String userID = intent.getStringExtra("UserID");
return START_STICKY;
}
注意:以上答案指定使用 getIntent() 方法获取 Intent,这在服务上下文中不正确
【讨论】:
Unable to start service Intent: not found
第一个上下文(可以是活动/服务等)
对于服务,您需要覆盖 onStartCommand,您可以直接访问 intent:
Override
public int onStartCommand(Intent intent, int flags, int startId) {
你有几个选择:
Intent mIntent = new Intent(this, Example.class);
Bundle extras = mIntent.getExtras();
extras.putString(key, value);
2) 创建一个新的捆绑包
Intent mIntent = new Intent(this, Example.class);
Bundle mBundle = new Bundle();
mBundle.extras.putString(key, value);
mIntent.putExtras(mBundle);
3)使用Intent的putExtra()快捷方式
Intent mIntent = new Intent(this, Example.class);
mIntent.putExtra(key, value);
新上下文(可以是活动/服务等)
Intent myIntent = getIntent(); // this getter is just for example purpose, can differ
if (myIntent !=null && myIntent.getExtras()!=null)
String value = myIntent.getExtras().getString(key);
}
注意: Bundle 对所有原始类型、Parcelable 和 Serializable 都有“get”和“put”方法。我只是将字符串用于演示目的。
【讨论】:
如果你绑定你的服务,你会在onBind(Intent intent)获得Extra。
活动:
Intent intent = new Intent(this, LocationService.class);
intent.putExtra("tour_name", mTourName);
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
服务:
@Override
public IBinder onBind(Intent intent) {
mTourName = intent.getStringExtra("tour_name");
return mBinder;
}
【讨论】:
Arrays.toString(yourAry[]) 会在这里为您提供帮助。
另一种可能性是使用intent.getAction:
服务中:
public class SampleService inherits Service{
static final String ACTION_START = "com.yourcompany.yourapp.SampleService.ACTION_START";
static final String ACTION_DO_SOMETHING_1 = "com.yourcompany.yourapp.SampleService.DO_SOMETHING_1";
static final String ACTION_DO_SOMETHING_2 = "com.yourcompany.yourapp.SampleService.DO_SOMETHING_2";
static final String ACTION_STOP_SERVICE = "com.yourcompany.yourapp.SampleService.STOP_SERVICE";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent.getAction();
//System.out.println("ACTION: "+action);
switch (action){
case ACTION_START:
startingService(intent.getIntExtra("valueStart",0));
break;
case ACTION_DO_SOMETHING_1:
int value1,value2;
value1=intent.getIntExtra("value1",0);
value2=intent.getIntExtra("value2",0);
doSomething1(value1,value2);
break;
case ACTION_DO_SOMETHING_2:
value1=intent.getIntExtra("value1",0);
value2=intent.getIntExtra("value2",0);
doSomething2(value1,value2);
break;
case ACTION_STOP_SERVICE:
stopService();
break;
}
return START_STICKY;
}
public void startingService(int value){
//calling when start
}
public void doSomething1(int value1, int value2){
//...
}
public void doSomething2(int value1, int value2){
//...
}
public void stopService(){
//...destroy/release objects
stopself();
}
}
活动中:
public void startService(int value){
Intent myIntent = new Intent(SampleService.ACTION_START);
myIntent.putExtra("valueStart",value);
startService(myIntent);
}
public void serviceDoSomething1(int value1, int value2){
Intent myIntent = new Intent(SampleService.ACTION_DO_SOMETHING_1);
myIntent.putExtra("value1",value1);
myIntent.putExtra("value2",value2);
startService(myIntent);
}
public void serviceDoSomething2(int value1, int value2){
Intent myIntent = new Intent(SampleService.ACTION_DO_SOMETHING_2);
myIntent.putExtra("value1",value1);
myIntent.putExtra("value2",value2);
startService(myIntent);
}
public void endService(){
Intent myIntent = new Intent(SampleService.STOP_SERVICE);
startService(myIntent);
}
最后,在 Manifest 文件中:
<service android:name=".SampleService">
<intent-filter>
<action android:name="com.yourcompany.yourapp.SampleService.ACTION_START"/>
<action android:name="com.yourcompany.yourapp.SampleService.DO_SOMETHING_1"/>
<action android:name="com.yourcompany.yourapp.SampleService.DO_SOMETHING_2"/>
<action android:name="com.yourcompany.yourapp.SampleService.STOP_SERVICE"/>
</intent-filter>
</service>
【讨论】:
活动:
int number = 5;
Intent i = new Intent(this, MyService.class);
i.putExtra("MyNumber", number);
startService(i);
服务:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getExtras() != null){
int number = intent.getIntExtra("MyNumber", 0);
}
}
【讨论】:
private void startFloatingWidgetService() {
startService(new Intent(MainActivity.this,FloatingWidgetService.class)
.setAction(FloatingWidgetService.ACTION_PLAY));
}
而不是:
private void startFloatingWidgetService() {
startService(new Intent(FloatingWidgetService.ACTION_PLAY));
}
因为当您尝试第二个时,您会收到错误消息: java.lang.IllegalArgumentException:服务意图必须明确:Intent { act=com.floatingwidgetchathead_demo.SampleService.ACTION_START }
那么你的服务应该是这样的:
static final String ACTION_START = "com.floatingwidgetchathead_demo.SampleService.ACTION_START";
static final String ACTION_PLAY = "com.floatingwidgetchathead_demo.SampleService.ACTION_PLAY";
static final String ACTION_PAUSE = "com.floatingwidgetchathead_demo.SampleService.ACTION_PAUSE";
static final String ACTION_DESTROY = "com.yourcompany.yourapp.SampleService.ACTION_DESTROY";
@SuppressLint("LogConditional")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent.getAction();
//System.out.println("ACTION: "+action);
switch (action){
case ACTION_START:
Log.d(TAG, "onStartCommand: "+action);
break;
case ACTION_PLAY:
Log.d(TAG, "onStartCommand: "+action);
addRemoveView();
addFloatingWidgetView();
break;
case ACTION_PAUSE:
Log.d(TAG, "onStartCommand: "+action);
break;
case ACTION_DESTROY:
Log.d(TAG, "onStartCommand: "+action);
break;
}
return START_STICKY;
}
【讨论】:
这就是我将数据从Activity 传递到IntentService 的方式。
我的一个application 有这种情况。
1) 发送数据(活动代码)
Intent intent = new Intent(MusicActivity.class, DownloadSongService.class);
String songUrl = "something";
intent.putExtra(YOUR_KEY_SONG_NAME, songUrl);
startService(intent);
2)在Service中获取数据(IntentService代码)
您可以在onHandleIntent() 方法中访问意图
public class DownloadSongService extends IntentService {
@Override
protected void onHandleIntent(@Nullable Intent intent) {
String songUrl = intent.getStringExtra("YOUR_KEY_SONG_NAME");
// Download File logic
}
}
【讨论】:
服务:启动服务可能会产生副作用,最好的方式是使用信使和传递数据。
private CallBackHandler mServiceHandler= new CallBackHandler(this);
private Messenger mServiceMessenger=null;
//flag with which the activity sends the data to service
private static final int DO_SOMETHING=1;
private static class CallBackHandler extends android.os.Handler {
private final WeakReference<Service> mService;
public CallBackHandler(Service service) {
mService= new WeakReference<Service>(service);
}
public void handleMessage(Message msg) {
//Log.d("CallBackHandler","Msg::"+msg);
if(DO_SOMETHING==msg.arg1)
mSoftKeyService.get().dosomthing()
}
}
Activity:Get Messenger from Intent 填充它传递数据并将消息传递回服务
private Messenger mServiceMessenger;
@Override
protected void onCreate(Bundle savedInstanceState) {
mServiceMessenger = (Messenger)extras.getParcelable("myHandler");
}
private void sendDatatoService(String data){
Intent serviceIntent= new
Intent(BaseActivity.this,Service.class);
Message msg = Message.obtain();
msg.obj =data;
msg.arg1=Service.DO_SOMETHING;
mServiceMessenger.send(msg);
}
【讨论】:
如果你使用的是 kotlin,你可以试试下面的代码,
在发送活动中,
val intent = Intent(context, RecorderService::class.java);
intent.putExtra("filename", filename);
context.startService(intent)
在服务中,
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
if (intent != null && intent.extras != null)
val filename = intent.getStringExtra("filename")
}
【讨论】: