2

Quelle est la méthode appropriée pour appeler une fonction dans la fenêtre Activity de mon application à partir d'un widget situé sur l'écran d'accueil? Pour mon exemple, j'ai un thread d'arrière-plan qui est initialisé dans ma classe Activity, et j'aimerais pouvoir appuyer sur le widget depuis l'écran d'accueil pour appeler des fonctions spécifiques pour démarrer/arrêter le thread sans avoir à entrer dans l'application.Comment appeler la fonction dans Activity à partir du widget HomeScreen

Ci-dessous une dépouillé et la version barebone de l'activité, je travaille avec:

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 
    } 
} 

est Ci-dessous le code barebone pour le widget écran d'accueil:

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

Voici ce que mon actuel meilleur solution est: De la recherche que j'ai faite jusqu'à présent, il semble que je dois continuer à utiliser putExtra() puis getExtra() avec l'intention qui est envoyé à partir du widget, et ajouter une chaîne pour dire s'il faut appeler startThread() ou stopThread() en fonction de l'état du thread. L'objectif actuel est de l'utiliser comme ceci:

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

Et ce serait RAN le plus probable dans une version surchargée de onNewIntent(). Cependant, l'intention envoyée par le widget entraîne également un appel à onCreate(), ce que je ne veux pas que cela se produise car cela relancerait le thread et d'autres codes d'initialisation que je vais avoir seront également réexécutés. J'ai essayé de placer le launchMode à singleTask, mais il appellerait toujours onCreate() plutôt que seulement onNewIntent(). Pour récapituler, j'aimerais pouvoir appuyer sur le widget de l'écran d'accueil, et commencer ou arrêter le thread, ou plus généralement appeler une fonction spécifique dans un MainActivity existant.

Répondre

0

Entre la réponse de Michael Spitsin et the answer here, j'ai été en mesure de trouver un moyen d'exécuter des méthodes spécifiques lorsque les boutons du widget écran d'accueil sont cliqués. Comme Michael l'a dit, il y a une différence entre getBroadcast et getActivity. Dans ce cas, j'ai pu utiliser getBroadcast pour diffuser une intention, mais au lieu d'avoir l'intention soit d'ouvrir le MainActivity, je this.class, où « ce » est la classe que la fonction updateAppWidget est.

Qu'est-ce que ceci est diffusé une intention à elle-même, et est attrapé dans le onReceive(Context,Intent) dans la même classe. Assurez-vous d'utiliser addAction sur l'intention que vous envoyez pour donner à votre intention un moyen de se distinguer des autres intentions qui sont interceptées par onReceive. Vous devez simplement surcharger la méthode avec votre propre implémentation, comme le fait l'autre réponse. Ci-dessous est la version dénudée de ce que j'ai obtenu pour obtenir le widget de travail:

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 
      } 
     } 
    } 
} 
1

Je ne suis pas un expert dans Widget construction processus, mais je suppose que vous devez changer:

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

Pour:

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

Puisque vous devez fournir une interaction avec l'application , vous n'avez pas besoin d'attacher votre widget à une activité spécifique. Au lieu de cela, vous devez utiliser le mécanisme de messagerie. Dans Android, il s'agit du BroadcastReciever. Par exemple, vous l'utilisez pour interagir avec votre service "Démarrer". Vous pouvez lire here about simple example.

En outre, selon this réponse que nous sommes arrivés à la solution, que vous devez vous inscrire recepteur dans le manifeste:

Ensuite, dans la méthode onRecieve vous pouvez analyser votre intention et faire tout ce que vous vouloir. Dans votre cas, je recommanderais de transporter travailler avec le fond de Activity à Service, puisque l'activité peut être fermée (okey, Service aussi, mais il peut être restauré et exécuté sans écran). Et dans MyWidgetReciever.onReceive vous devez commencer le service en passant "intention d'arrêt". Je ne suis pas sûr, mais, probablement, vous pouvez attraper la diffusion dans le service directement, pas dans le récepteur externe, mais il pourrait être la situation quand le service sera tué, ainsi il ne s'occupera pas de votre diffusion.