【问题标题】:How to call function in Activity from HomeScreen Widget如何从 HomeScreen Widget 调用 Activity 中的函数
【发布时间】:2017-01-20 16:55:59
【问题描述】:

从位于主屏幕上的小部件调用我的应用程序Activity 中的函数的正确方法是什么?对于我的示例,我有一个在我的 Activity 类中初始化的后台线程,并且希望能够从主屏幕按下小部件以调用特定函数来启动/停止线程,而无需进入应用程序。

以下是我正在使用的 Activity 的精简和准系统版本:

public class MainActivity extends AppCompatActivity {
    private Thread thread;
    private Runnable runner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startThread();
    }

    private void startThread() {
        //start/restart the thread
    }

    public void stopThread() {
        //interupt the thread
    }   
}

以下是主屏幕小部件的准系统代码:

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {

    Intent intent = new Intent(context, MainActivity.class);

    intent.putExtra("Goal","Stop");
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.speed_widget);
    views.setOnClickPendingIntent(R.id.widgetButton, pendingIntent);

    appWidgetManager.updateAppWidget(appWidgetId, views);
}

这是我目前最好的解决方案:从我目前所做的研究来看,我似乎需要继续使用putExtra(),然后将getExtra() 与从小部件发送的 Intent 一起使用,并且添加一个字符串来说明是否根据线程的状态调用startThread()stopThread()。目前的目标是这样使用它:

    String intentGoal = getIntent().getExtras().getString("Goal");
    if(intentGoal.compareTo("Stop")==0){
        stopThread();
    }else if(intentGoal.compareTo("Start")==0){
        startThread();
    }

它很可能在onNewIntent() 的重载版本中运行。但是,从小部件发送的意图也会导致对onCreate() 的调用,我不希望发生这种情况,因为它会重新启动线程,并且我拥有的各种其他初始化代码也将被重新运行。我尝试将launchMode 设置为singleTask,但它仍然会调用onCreate() 而不仅仅是onNewIntent()。回顾一下,我希望能够按下主屏幕小部件,然后启动或停止线程,或者更一般地调用现有“MainActivity”中的特定函数。

【问题讨论】:

    标签: android multithreading android-intent widget android-widget


    【解决方案1】:

    我不是小部件构建过程方面的专家,但我认为您需要更改:

    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    

    收件人:

    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    

    由于您需要提供与应用程序的一些交互,因此您无需将小部件附加到特定活动。取而代之的是,您需要使用这么说的消息传递机制。在 Android 中是BroadcastReciever。例如,您使用它与您的“启动”服务进行交互。你可以阅读here about simple example

    另外,根据this的回答,我们找到了解决方案,你需要在manifest中注册reciever:

    然后在onRecieve 方法中,您可以解析您的意图并做任何您想做的事情。在您的情况下,我建议将背景工作从Activity 传输到Service,因为可以关闭活动(好吧,Service 也可以,但它可以在没有屏幕的情况下恢复和运行)。在MyWidgetReciever.onReceive 中,您需要通过“停止”意图启动服务。

    我不确定,但是,也许您可​​以直接在服务中捕获广播,而不是在外部接收器中,但可能是服务将被杀死的情况,因此它不会处理您的广播。

    【讨论】:

      【解决方案2】:

      在 Michael Spitsin 的回答和 the answer here 之间,我能够找到一种在单击主屏幕小部件按钮时执行特定方法的方法。正如迈克尔所说,getBroadcastgetActivity 之间是有区别的。对于这种情况,我能够使用getBroadcast 来广播一个意图,但我没有打算打开MainActivity,而是使用this.class,其中“this”是函数 updateAppWidget 所在的类.

      这样做是向自己广播一个意图,并在同一类的onReceive(Context,Intent) 中捕获。确保在您发送的 Intent 上使用 addAction 以使您的意图与onReceive 捕获的其他 Intent 区分开来您只需要使用自己的实现重载该方法,类似于我链接的其他答案去做。下面是我让小部件工作的精简版:

      public class MyWidget extends AppWidgetProvider {
          public static String YOUR_ACTION = "YourAction";
      
          static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
      
              Intent intent = new Intent(context, SpeedWidget.class);
              intent.setAction(YOUR_ACTION);
      
              PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
              RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.speed_widget);
              views.setOnClickPendingIntent(R.id.widgetButton, pendingIntent);
      
              appWidgetManager.updateAppWidget(appWidgetId, views);
      
          }
      
          @Override
          public void onReceive(Context context, Intent intent) {
              super.onReceive(context, intent);
      
              if (intent.getAction().equals(YOUR_ACTION)) {
                      //THIS IS WHERE YOUR CODE WILL BE EXECUTED
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-12-01
        • 2021-02-20
        • 2012-03-21
        • 2015-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-24
        相关资源
        最近更新 更多