Android服务展示吐司

时间:2014-02-02 20:38:32

标签: android service toast

此代码应该使用服务来显示Toast消息。没有错误,但它没有显示吐司。

主要活动

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Intent i= new Intent(this, BackgroundMusic.class);
    this.startService(i); 

}



}

服务(它被称为背景音乐,但现在它应该显示一个祝酒消息)

public class BackgroundMusic extends IntentService {

 public BackgroundMusic() {
      super("BackgroundMusic");
  }



 @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.
     Context context = getApplicationContext();
     CharSequence text = "Hello toast!";
     int duration = Toast.LENGTH_SHORT;

     Toast toast = Toast.makeText(context, text, duration);
     toast.show();
 }



}

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.starwars"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="18" />

<application
    android:allowBackup="true"
    android:debuggable="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
     <service android:name=".BackgroundMusic" />
    <activity
        android:name="com.example.starwars.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:label="@string/app_name" android:name="BackgroundMusic"/>
</application>

</manifest>

3 个答案:

答案 0 :(得分:69)

试试这个:

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

答案 1 :(得分:22)

See this part of the docs

  

(IntentService有一些限制:

     

它无法直接与您的用户界面互动。把它   在UI中,您必须将它们发送到活动。

您需要将其放在主Thread上。请参阅the answer here by rony的方法。

full documentation on IntentService

  

使用工作线程

依次处理每个Intent

答案 2 :(得分:0)

最好将所有GUI活动(包括toast)委派给正在使用您的服务的Activity。例如,我有一个绑定服务,用于在后台进行位置捕获,并在我的应用程序可见时将更新发布到屏幕上。

我的应用实现了一个简单的界面:

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

我的班级def看起来像这样:

public class MyActivity extends Activity implements ICapture {
...

这是处理绑定服务的东西:

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

这里唯一不标准的是

captureService.setOwner(ICapture.this);

为服务提供了应用程序对ICapture的实现的参考。请参阅下文,了解它是如何使用的。

我在onCreate()中启动服务:

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

我使用这些方法在应用程序可见且能够满足GUI请求时告诉服务:

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

@Override
public void onResume() {
    super.onResume();
    if (captureService != null) {
        captureService.setOwner(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;
        }
    }
}

所有这些都是您可以在其他地方找到的非常标准的代码。主要的是,当发生位置更新时,代码通过其实现的ICapture接口调用应用程序,但如果应用程序可见则仅 。在应用程序中实现onPause()和onResume()可确保服务知道应用程序何时可以接受呼叫。

要进行Toast弹出窗口,请将另一个方法添加到ICapture界面并在应用程序中实现它。您的服务可以在知道屏幕可以接受的任何时候调用它。事实上,即使应用程序不在前台,Toast弹出窗口仍然会出现,但我相信当屏幕变为非活动状态时它们会被阻止,这反过来会阻止服务。因此,只有当应用程序位于前台时才发送它们会更好。