【问题标题】:Pass data from Activity to Service using an Intent使用 Intent 将数据从 Activity 传递到 Service
【发布时间】:2011-03-18 14:52:27
【问题描述】:

如何在 Android Service 中获取从调用 Activity 传递的数据?

【问题讨论】:

    标签: android android-intent android-activity service


    【解决方案1】:

    关于“如何通过意图从 Activity 向服务发送数据”这个问题的准确答案,您是否必须覆盖接收意图对象的 onStartCommand() 方法:

    当您创建Service 时,您应该覆盖onStartCommand() 方法,因此如果您仔细查看下面的签名,您会收到传递给它的intent 对象:

      public int onStartCommand(Intent intent, int flags, int startId)
    

    因此,您将从活动中创建意图对象以启动服务,然后将数据放入意图对象中,例如,您希望将 UserIDActivity 传递到 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,这在服务上下文中不正确

    【讨论】:

    • 这应该是公认的答案。 Service 接受的答案是错误的。
    • 我有这个错误:Unable to start service Intent: not found
    • getintent 现已弃用
    【解决方案2】:

    第一个上下文(可以是活动/服务等)

    对于服务,您需要覆盖 onStartCommand,您可以直接访问 intent

    Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    

    你有几个选择:

    1) 使用来自IntentBundle

    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”方法。我只是将字符串用于演示目的。

    【讨论】:

    • 但是我们不能在服务中使用 getIntent() 方法。当我们将价值从活动发送到服务时,如何实现这一点?
    • 只使用意图不需要getIntent()
    • 这不应该是公认的答案,因为这不是服务的正确解决方案。
    【解决方案3】:

    如果你绑定你的服务,你会在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;
    }
    

    【讨论】:

    • @ChefPharaoh 这是个好问题。尝试记录意图的值。 Arrays.toString(yourAry[]) 会在这里为您提供帮助。
    • 因为我想传递一个自定义类,所以我发现我只需要实现 parcelable 接口,一切都很好。不过还是谢谢。
    【解决方案4】:

    另一种可能性是使用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>
    

    【讨论】:

    • 您多次启动服务...是否意味着每次都会创建同一服务的多个实例?
    • 服务具有单例模式。 stackoverflow.com/questions/2518238/…
    • "switch(action)" action可以为null
    • 不在我的代码中:始终使用方法调用服务。无论如何,这是一个简单的代码来解释如何做到这一点。在实际程序中,您总是必须检查这些事情,以及参数是否以适当的值到达
    【解决方案5】:

    活动:

    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);
        }
    }
    

    【讨论】:

      【解决方案6】:

      这是一种更好、更安全的方法。像魅力一样工作!

         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;
      
      }
      

      【讨论】:

        【解决方案7】:

        将数据从 Activity 传递到 IntentService

        这就是我将数据从Activity 传递到IntentService 的方式。

        我的一个application 有这种情况。

        MusicActivity ------url(String)------> 下载歌曲服务

        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
            
            }
        
        }
        

        【讨论】:

          【解决方案8】:

          服务:启动服务可能会产生副作用,最好的方式是使用信使和传递数据。

          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);
          }
          

          【讨论】:

            【解决方案9】:

            如果你使用的是 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")
            
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-08-17
              • 1970-01-01
              • 2014-09-14
              • 1970-01-01
              • 2012-04-14
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多