Android Service to show toast

后端 未结 3 1158
-上瘾入骨i
-上瘾入骨i 2020-12-09 00:55

This code is supposed to use a service to show a toast message. There are no errors, but it doesn\'t show the toast.

main activity

public class Main         


        
相关标签:
3条回答
  • 2020-12-09 01:32

    See this part of the docs

    (An IntentService has a few limitations:

    It can't interact directly with your user interface. To put its results in the UI, you have to send them to an Activity.

    You need to put it on the main Thread. See the answer here by rony of a way to do that.

    and from the full documentation on IntentService

    handles each Intent in turn using a worker thread

    0 讨论(0)
  • 2020-12-09 01:43

    It's probably best to delegate all GUI activities (including toast) to the Activity that is using your Service. For example, I have a bound service for doing location capture in the background and posting updates to the screen while my app is visible.

    My app implements a simple interface:

    public interface ICapture {
        void update(Location location);
    }
    

    and my class def looks like this:

    public class MyActivity extends Activity implements ICapture {
    ...
    

    Here's the stuff for handling the bound service:

    private CaptureService captureService;
    private ServiceConnection captureServiceConnection = new ServiceConnection() {
    
        public void onServiceConnected(ComponentName className, IBinder service) {
            CaptureService.MyLocalBinder binder = (CaptureService.MyLocalBinder) service;
            captureService = binder.getService();
            captureService.setOwner(ICapture.this);
        }
    
        public void onServiceDisconnected(ComponentName arg0) {
        }
    };
    

    The only thing here that's not standard is the line

    captureService.setOwner(ICapture.this);
    

    which provides the service with a reference to the app's implementation of ICapture. See below for how it's used.

    I start the Service in onCreate():

        Intent intent = new Intent(this, CaptureService.class);
        startService(intent);
        bindService(intent, captureServiceConnection, Context.BIND_AUTO_CREATE);
    

    and I use these methods to tell the service when the app is visible and able to satisfy GUI requests:

    @Override
    public void onPause() {
        super.onPause();
        if (captureService != null) {
            captureService.setOwner(null);
        }
    }
    
    @Override
    public void onResume() {
        super.onResume();
        if (captureService != null) {
            captureService.setOwner(this);
        }
    }
    

    The Service looks like this:

    package *****;
    
    import android.app.Service;
    import android.content.Intent;
    import android.location.Location;
    import android.os.Binder;
    import android.os.Bundle;
    import android.os.IBinder;
    
    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.GooglePlayServicesUtil;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;
    
    public class CaptureService extends Service implements
            com.google.android.gms.location.LocationListener,
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener {
    
        private static final long UPDATE_INTERVAL = 1000 * 10;
        private static final long FASTEST_INTERVAL = 1000 * 5;
    
        private final IBinder myBinder = new MyLocalBinder();
    
        private GoogleApiClient mGoogleApiClient;
        private LocationRequest mLocationRequest;
        private ICapture owner;
    
        @Override
        public void onCreate() {
            if (isGooglePlayServicesAvailable()) {
                mGoogleApiClient = new GoogleApiClient.Builder(this)
                        .addConnectionCallbacks(this)
                        .addOnConnectionFailedListener(this)
                        .addApi(LocationServices.API)
                        .build();
                mLocationRequest = new LocationRequest();
                mLocationRequest.setInterval(UPDATE_INTERVAL);
                mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
                mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
                mGoogleApiClient.connect();
            }
        }
    
        @Override
        public void onConnected(Bundle bundle) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    
        @Override
        public void onConnectionSuspended(int i) {
        }
    
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
        }
    
        /**************************************************************************
         * The binder that returns the service activity.
         */
        public class MyLocalBinder extends Binder {
            public CaptureService getService() {
                return CaptureService.this;
            }
        }
    
        @Override
        public IBinder onBind(Intent arg0) {
            return myBinder;
        }
    
        /**************************************************************************
         * Bound methods.
         *
         * Set the owner, to be notified when the position changes.
         *
         * @param owner
         */
        public void setOwner(ICapture owner) {
            this.owner = owner;
        }
    
        /**************************************************************************
         * Start the service and keep it running when the phone is idle.
         */
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            return START_STICKY;
        }
    
        /**
         * Callback when the location changes. Inform the owner.
         *
         * @param location
         */
        @Override
        public void onLocationChanged(Location location) {
            if (owner != null) {
                owner.update(location);
            }
        }
    
        private boolean isGooglePlayServicesAvailable() {
            int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
            if (ConnectionResult.SUCCESS == status) {
                return true;
            } else {
                return false;
            }
        }
    }
    

    All this is pretty standard code you can find elsewhere. The main thing is that when a location update occurs the code calls the app via its implemented ICapture interface, but only if the app is visible. The implementation of onPause() and onResume() in the app makes sure that the service knows when the app can accept calls.

    To do a toast popup, add another method to the ICapture interface and implement it in the app. Your service can then call it any time it knows the screen can accept it. In fact, toast popups will still come through even when the app isn't in the foreground, but I believe they get blocked when the screen goes inactive, which in turn blocks the service. So it's better to only send them when the app is in the foreground.

    0 讨论(0)
  • 2020-12-09 01:55

    Try this:

    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
    
        @Override
        public void run() {
                Toast.makeText(YourService.this.getApplicationContext(),"My Awesome service toast...",Toast.LENGTH_SHORT).show();
                }
            });
    
    0 讨论(0)
提交回复
热议问题