J'ai créé une application dans laquelle j'ai enregistré un récepteur de diffusion dans ma classe principale (Main Activity
) et chaque fois que je reçois quelque chose dans ma BroadcastReceiver
, je souhaite mettre à jour l'interface utilisateur, par exemple. Je souhaite afficher un message d’alerte ou définir une vue textuelle de ma MainActivity
. Je reçois toutes les valeurs dans mon récepteur mais je ne peux pas les définir. Quelqu'un peut-il m'aider pour mettre à jour mon interface utilisateur dans la variable BroadcastReceiver
?.
Ma classe BroadcastReceiver est la classe interne de MainActivity comme ceci: -
public class MainActivity extends Activity {
..........
public static class NissanTabBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences shrd = context.getSharedPreferences("NissanGallery", context.MODE_WORLD_READABLE);
type = shrd.getString("type", "null");
badges = shrd.getString("badge_count", "null");
//badge_tips_text.setText(badges);
/*Editor edit = shrd.edit();
edit.remove("type");*/
Toast.makeText(context, "" + type + "\n" + badge_tips_text.getText().toString(), Toast.LENGTH_LONG).show();
}
}
}
Toute aide sera appréciable
Merci
Je vous suggère d'utiliser un gestionnaire.
handler = new Handler()
post()
de votre instance de gestionnaire dans la méthode onReceive()
pour soumettre le fichier Runnable qui met à jour l'interface utilisateur.C’est la solution la plus propre que je puisse imaginer.
public class MainActivity extends Activity {
private MyReceiver receiver;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
receiver = new MyReceiver(new Handler()); // Create the receiver
registerReceiver(receiver, new IntentFilter("some.action")); // Register receiver
sendBroadcast(new Intent("some.action")); // Send an example Intent
}
public static class MyReceiver extends BroadcastReceiver {
private final Handler handler; // Handler used to execute code on the UI thread
public MyReceiver(Handler handler) {
this.handler = handler;
}
@Override
public void onReceive(final Context context, Intent intent) {
// Post the UI updating code to our Handler
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, "Toast from broadcast receiver", Toast.LENGTH_SHORT).show();
}
});
}
}
}
Mon cas était de mettre à jour le champ de texte dans l'un des fragments hébergés par MainActivity.La solution la plus simple que j'ai trouvée était la suivante: -
Dans ma classe MainActivity, j'ai récupéré l'instance active de MainActivtiy. C'est ma MAinActivity.
private static MainActivity mainActivityRunningInstance;
public static MainActivity getInstace(){
return mainActivityRunningInstance;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivityRunningInstance =this;
----------
}
Maintenant, dans la méthode onRecieve de Broadcast reciever, récupérez cette instance et appelez la méthode update
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().matches(Intents.PROVIDER_CHANGED_ACTION)) {
String textValue="the text field value";
// the null check is for, if the activity is not running or in paused state, in my case the update was required onlyif the main activity is active or paused
if(MainActivity.getInstace()!=null)
MainActivity.getInstace().updateUI(textValue);
}
Maintenant pour la partie où nous devons exécuter la mise à jour dans UIThread, la méthode updateUI de MainActivity appellera la méthode de mise à jour des fragments.
public void updateUI(final String str) {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
//use findFragmentById for fragments defined in XML ((SimpleFragment)getSupportFragmentManager().findFragmentByTag(fragmentTag)).updateUI(str);
}
});
}
et la dernière étape met à jour le champ de texte du fragment
public void updateUI(String str){
tv_content.setText(str);
}
et Bingo, c'est fait. J'ai référé this link pour résoudre mon problème. J'espère que ça aidera les autres.
Utilisez runOnUiThread
:
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// show alert
}
});
BroadcastReceiver
dans différentes activités BroadcastReceiver
dans un fichier séparé et souhaitez accéder aux méthodes Activity
, aux éléments de l'interface utilisateur, etc. Dans ces cas, l'utilisation d'une interface est une excellente approche. J'expliquerai l'avantage et un cas d'utilisation plus en détail. Mais d'abord, voyez comment ça se passe.
1) Créer une interface
public interface MyBroadcastListener{
public void doSomething(String value);
}
2) Initialiser le récepteur dans votre BroadcastReceiver
public class MyReceiver extends BroadcastReceiver {
private MyBroadcastListener listener;
public MyReceiver(MyBroadcastListener listener){
this.listener = listener;
}
@Override
public void onReceive(Context context, Intent intent) {
listener.doSomething("Some Result");
}
}
3) Implémentez l'interface dans votre activité et remplacez la méthode
public MainActivity extends AppCompatActivity implements MyBroadcastListener{
// Your Activity code
public void updateUI(String msg) {
TextView textView = (TextView) findViewById(R.id.textView);
textView .setText(msg);
}
@Override
public void doSomething(String result){
updateUI(result); // Calling method from Interface
}
}
L'utilisation de l'interface rend
BroadcastReceiver
indépendant de toutActivity
. Disons à l'avenir que vous souhaitez utiliser cetteBroadCastReceiver
avec une autre activité qui prend le résultat deBroadcastReceiver
et lancez DetailActivity avec le résultat. C'est un complètement tâche différente mais vous utiliserez la mêmeBroadcastReceiver
sans même changer le code dans laBroadcastReceiver
.
Comment faire ça?
Simple! Implémentez l'interface dans les variables Activity
et Override. C'est tout!
public ListActivity extends AppCompatActivity implements MyBroadcastListener{
// Your Activity code goes here
public void startDetailActivity(String title) {
Intent i = new Intent(ListActivity,this, DetailActivity.class);
i.putExtra("Title", title);
startActivity(i);
}
@Override
public void doSomething(String result){
startDetailActivity(String title); // Calling method from Interface
}
}
J'utilise une approche complètement différente pour cela.Passer l'instance de gestionnaire pour émettre le destinataire en le mettant dans l'intention.Than récepteur a utilisé ce gestionnaire pour envoyer un message à votre classe d'activité qui met à jour l'interface utilisateur de votre méthode onHandleMessage de votre gestionnaire personnalisé classe.
create handler class like
public class MyHandler extends Handler{
onHandlerMessage(Message msg){//do whatever you want here after broadcast get fired}
}
maintenant, utilisez Myhandler handler=new MyHandler();
créer cet objet de gestionnaire sur la portée de niveau global en activité.
Maintenant, mettez ce gestionnaire dans votre intention par putExtra
et envoyez ensuite cette intention via sendBraodcast(intent)
.
dans la classe de récepteur de diffusion, obtenez cet objet de gestionnaire par getExtras et utilisez-le comme ci-dessousin onReceive()
handler.sendEmptyMessage();
L'utilisation de getters et de setters peut facilement résoudre ce problème.
déclarez simplement une classe comme suit.
public class DetailsGetters {
private View view;
public View getview() {
return view;
}
public void setview(View view) {
this.view = view;
}
}
Dans votre activité principale ou dans votre activité de fragment, créez une instance de la classe DetailsGetters.
DetailsGetters newdetailsinstance=new DetailsGetters();
Avant de reprendre la vue callnewdetailsinstance.setview(view);
Sur le récepteur de diffusion, obtenez la vue sous le nom newdetailsinstance.getview(view);
La suite peut être utilisée pour obtenir une vue du fragment et mettre à jour Ui en utilisant setText et ainsi de suite.
Pour mettre à jour l'interface utilisateur de l'activité principale, passez Textview, changez la classe DeailsGetters et créez des accesseurs et des passeurs pour Textview. J'espère que cela aide pour quelqu'un.
J'ai utilisé Intention pour informer Broadcast Receiver de l'instance de gestionnaire du fil d'activité principal et ai utilisé Message pour transmettre un message à l'activité principale.
J'ai utilisé un tel mécanisme pour vérifier si Broadcast Receiver est déjà enregistré ou non. Parfois, cela est nécessaire lorsque vous enregistrez votre récepteur de radiodiffusion de manière dynamique et que vous ne voulez pas le faire deux fois, ou que vous présentez à l'utilisateur si le récepteur de diffusion est en cours d'exécution.
Activité principale:
public class Example extends Activity {
private BroadCastReceiver_example br_exemple;
final Messenger mMessenger = new Messenger(new IncomingHandler());
private boolean running = false;
static class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
running = false;
switch (msg.what) {
case BroadCastReceiver_example.ALIVE:
running = true;
....
break;
default:
super.handleMessage(msg);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter();
filter.addAction("pl.example.CHECK_RECEIVER");
br_exemple = new BroadCastReceiver_example();
getApplicationContext().registerReceiver(br_exemple , filter); //register the Receiver
}
// call it whenever you want to check if Broadcast Receiver is running.
private void check_broadcastRunning() {
/**
* checkBroadcastHandler - the handler will start runnable which will check if Broadcast Receiver is running
*/
Handler checkBroadcastHandler = null;
/**
* checkBroadcastRunnable - the runnable which will check if Broadcast Receiver is running
*/
Runnable checkBroadcastRunnable = null;
Intent checkBroadCastState = new Intent();
checkBroadCastState .setAction("pl.example.CHECK_RECEIVER");
checkBroadCastState .putExtra("mainView", mMessenger);
this.sendBroadcast(checkBroadCastState );
Log.d(TAG,"check if broadcast is running");
checkBroadcastHandler = new Handler();
checkBroadcastRunnable = new Runnable(){
public void run(){
if (running == true) {
Log.d(TAG,"broadcast is running");
}
else {
Log.d(TAG,"broadcast is not running");
}
}
};
checkBroadcastHandler.postDelayed(checkBroadcastRunnable,100);
return;
}
.............
}
Récepteur de diffusion:
public class BroadCastReceiver_example extends BroadcastReceiver {
public static final int ALIVE = 1;
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle extras = intent.getExtras();
String action = intent.getAction();
if (action.equals("pl.example.CHECK_RECEIVER")) {
Log.d(TAG, "Received broadcast live checker");
Messenger mainAppMessanger = (Messenger) extras.get("mainView");
try {
mainAppMessanger.send(Message.obtain(null, ALIVE));
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
.........
}
}
Dans mon cas, je souhaite mettre à jour le texte dans mon activité avec les SMS entrants. Ce que j'ai fait a été ajouté avec les informations requises à l'aide de putextra, puis a démarré l'activité depuis le récepteur de radiodiffusion:
Intent intentone = new Intent(context.getApplicationContext(), enroll.class);
intentone.putExtra("pinbody",message);
intentone.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentone);
Et puis, du côté du destinataire, c’est-à-dire que lors de l’inscription, j’ai extrait cette information à l’aide de ce qui suit et a mis à jour mon textview:
Bundle extras = getIntent().getExtras();
String message = extras.getString("pinbody");
Je ne sais pas si cela aide, mais cela vous mènera à ce que vous voulez.
À votre santé !
Vous devez définir Broadcast receiver comme classe interne, de cette manière, il aura accès à tous les champs pour mettre à jour l'interface utilisateur.
Voir cette application Plaid par Nick Butcher Plaid- Nick Butcher (Github)
J'ai utilisé Handler & sa méthode post (). Au lieu de runOnUiThread (). Pas besoin de convertir le contexte en activité. C'est une alternative à runOnUiThread ()
Handler handler = new Handler();
Runnable runnable = new Runnable() {
private long startTime = System.currentTimeMillis();
public void run() {
while (gameState == GameState.Playing) {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable(){
public void run() {
tvTime.setText("" + ((System.currentTimeMillis() - this.startTime) / 1000));
}
});
}
}
};
new Thread(runnable).start();