Handle onActivityResult on a Service

后端 未结 3 1987
野趣味
野趣味 2021-02-13 17:13

So i have a simple Question , it is Possible to Handle the Method onActivityResult() in a Service if this Activity was Started from the Same Service (Using Intent) ?

In

相关标签:
3条回答
  • 2021-02-13 17:38

    Thanks for a recent downvoting, whoever it was. The previous answer I gave back in 2012 is a total nonsesnse so I decided to write a proper one.

    You can not handle Activity result in a Service, but you can pass any data retrieved from onActivityResult() to a Service.

    If your Service is already running, you can call startService() with a new Intent handling the event, like so

    @Override
    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CODE && resultCode == RESULT_OK) {
            notifyService(data);
        }
    }
    
    private void notifyService(final Intent data) {
        final Intent intent = new Intent(this, MyService.class);
        intent.setAction(MyService.ACTION_HANDLE_DATA);
        intent.putExtra(MyService.EXTRA_DATA, data);
        startService(intent);
    }
    

    And handle action in a Service. If it is already running it will not be restarted, otherwise it will be started

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            final String action = intent.getAction();
            if (action != null) {
                switch (action) {
                    case ACTION_HANDLE_DATA:
                        handleData(intent.getParcelableExtra(EXTRA_DATA));
                        // Implement your handleData method. Remember not to confuse Intents, or even better make your own Parcelable
                        break;
                }
            }
        }
        return START_NOT_STICKY;
    }
    
    0 讨论(0)
  • 2021-02-13 17:44

    I recently stumbled upon the same issue, how to wire onActivityResult() outcome to a Service for an Activity started from the aforementioned Service. I did not want to store the Activity in a static variable given that Activity leak is a bad practice. So I added a static listener in the Activity handling onActivityResult() that implements an appropriate Interface and instantiated this listener as a private member of the Service class.

    The code in a simplified form looks like this:

    public class MyActivity extends FragmentActivity {
    
        public Interface ResultListener {
           onPositiveResult();
           onNegativeResult();
        }
    
        private static ResultListener mResultListener;
    
        public static setListener(ResultListener resultListener) {
            mResultListener = resultListener;
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (resultCode == Activity.RESULT_OK && mResultListener != null) {
                mResultListener.onPositiveResult(); 
            } else if (resultCode == Activity.RESULT_CANCELED && mResultListener != null) {
                mResultListener.onNegativeResult(); 
            }
            mResultListener = null;
        }
    }
    
    public class MyService {
    
        private MyActivity.ResultListener mListener = new MyActivity.ResultListener() {
            onPositiveResult() { 
                // do something on RESULT_OK
           }
           onNegativeResult() {
                // do something on RESULT_CANCELED 
           }
        }
    
        private void startActivityForResultFromHere() {
            MyActivity.setListener(mListener);
            Intent intent = new Intent();
            intent.setClass(this, MyActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        } 
    }
    

    As you can see I could not avoid static references due to device rotation issues, but I think this solution is more appropriate; albeit verbose.

    0 讨论(0)
  • 2021-02-13 17:49

    Open Transparent activity from service and use BroadcastReceiver in service. Follow the steps in detail.

    1. Open transparent activity from Service

    Intent i = new Intent(mContext, FloatingServiceSupportActivity.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    i.putExtra("action", "SpeechRegnition");
    mContext.startActivity(i);
    

    // For transparent activity use this code in AndroidManifest.xml

    <activity
    android:name=".FloatingServiceSupportActivity"
    android:theme="@style/Theme.Transparent" />
    

    2. Create BroadcastReceiver in Service

    BroadcastReceiver brOnActivityResult = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO:
        }
    };
    

    3. Register this broadcast in onCreate of Service

    IntentFilter brintent = new IntentFilter();
    brintent.addAction("brActionFloatingServiceOnActivityResult");
    mContext.registerReceiver(brOnActivityResult, brintent);
    

    4. Unregister this broadcast in onDestroy of Service

    mContext.unregisterReceiver(brOnActivityResult);
    

    5. Do work in Activity by using startActivityForResult and Send broadcast from Activity's (FloatingServiceSupportActivity) onActivityResult

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    
    Intent i = new Intent();
    i.setAction("brActionFloatingServiceOnActivityResult");
    i.putExtra("action", "initTextToSpeech");
    mActivity.sendBroadcast(i);
    
    mActivity.finish();
    }
    
    0 讨论(0)
提交回复
热议问题