从小部件启动/停止服务

Posted

技术标签:

【中文标题】从小部件启动/停止服务【英文标题】:Start/Stop Service from Widget 【发布时间】:2013-07-05 02:51:48 【问题描述】:

我想从小部件内部启动一个服务,我知道我可以使用 PendingIntent 来做到这一点

PendingIntent intent = PendingIntent.getService(context, 0, new Intent(context, MyService.class), Intent.FLAG_ACTIVITY_NEW_TASK);
remoteViews.setOnClickPendingIntent(R.id.buttonWidgetStartService, intent);

但问题是我已经在该按钮上使用了 PendingIntent 用于其他目的。 所以,我尝试使用

启动服务
context.startService(new Intent(context, MyService.class));

我在这里收到NullPointerException

这是我的代码:

public class WiNetWidget extends AppWidgetProvider 

    public static String TOGGLE_WINET = "ToggleWiNetService";
    private static boolean serviceRunning = false;
    private static Intent serviceIntent;
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 
        final int N = appWidgetIds.length;
        serviceIntent = new Intent(context, WiNetService.class);

        for (int i=0; i<N; i++) 
            int appWidgetId = appWidgetIds[i];
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_winet);

            remoteViews.setViewVisibility(R.id.buttonWidgetLoading, View.INVISIBLE);
            remoteViews.setViewVisibility(R.id.buttonWidgetStartService, View.VISIBLE);

            Intent newIntent = new Intent(context, WiNetWidget.class);
            newIntent.setAction(TOGGLE_WINET);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, newIntent, 0);
            remoteViews.setOnClickPendingIntent(R.id.buttonWidgetStartService, pendingIntent);
            remoteViews.setOnClickPendingIntent(R.id.buttonWidgetStopService, pendingIntent);

            appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
            Log.i(TOGGLE_WINET, "updated");
        
    

    @Override
    public void onReceive(Context context, Intent intent) 
        if(intent.getAction().equals(TOGGLE_WINET)) 
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_winet);
            if(serviceRunning) 
                context.stopService(serviceIntent);
                remoteViews.setViewVisibility(R.id.buttonWidgetStartService, View.VISIBLE);
                remoteViews.setViewVisibility(R.id.buttonWidgetStopService, View.INVISIBLE);
                Toast.makeText(context, "serviceStopped", Toast.LENGTH_SHORT).show();
             else 
                context.startService(serviceIntent);
                remoteViews.setViewVisibility(R.id.buttonWidgetStopService, View.VISIBLE);
                remoteViews.setViewVisibility(R.id.buttonWidgetStartService, View.INVISIBLE);
                Toast.makeText(context, "serviceStarted", Toast.LENGTH_SHORT).show();
            
            serviceRunning=!serviceRunning;
            ComponentName componentName = new ComponentName(context, WiNetWidget.class);
            AppWidgetManager.getInstance(context).updateAppWidget(componentName, remoteViews);
        
        super.onReceive(context, intent);
    

注意:如果我删除包含startServicestopService 的行,一切运行顺利。

提前致谢!! :)

【问题讨论】:

如果你使用context.startService(new Intent(context, MyService.class));而不是变量serviceIntent,它是否有效? @Neil Townsend:谢谢先生,它成功了。非常感谢!!你能解释一下为什么它以前不工作吗?再次感谢。 :) 完整答案见下文。 【参考方案1】:

问题是您创建了一次性Intent 一次,但多次使用它。每次要启动或停止Service 时,最好创建一个新的Intent,如下所示:

@Override
public void onReceive(Context context, Intent intent) 
    if(intent.getAction().equals(TOGGLE_WINET)) 
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_winet);

        // Create a fresh intent 
        Intent serviceIntent = new Intent(context, WiNetService.class);

        if(serviceRunning) 
            context.stopService(serviceIntent);
            remoteViews.setViewVisibility(R.id.buttonWidgetStartService, View.VISIBLE);
            remoteViews.setViewVisibility(R.id.buttonWidgetStopService, View.INVISIBLE);
            Toast.makeText(context, "serviceStopped", Toast.LENGTH_SHORT).show();
         else 
            context.startService(serviceIntent);
            remoteViews.setViewVisibility(R.id.buttonWidgetStopService, View.VISIBLE);
            remoteViews.setViewVisibility(R.id.buttonWidgetStartService, View.INVISIBLE);
            Toast.makeText(context, "serviceStarted", Toast.LENGTH_SHORT).show();
        
        serviceRunning=!serviceRunning;
        ComponentName componentName = new ComponentName(context, WiNetWidget.class);
        AppWidgetManager.getInstance(context).updateAppWidget(componentName, remoteViews);
    
    super.onReceive(context, intent);

【讨论】:

以上是关于从小部件启动/停止服务的主要内容,如果未能解决你的问题,请参考以下文章

为啥当主应用停止时我的小部件广播接收器服务停止

Android Widget 随机停止工作

屏幕打开/关闭时如何更新 Android 小部件?

MSSQLSERVER 服务启动后又停止了

微服务启动和停止

如何查看或停止Linux启动的服务?