How to add Snackbars in a BroadcastReceiver?

ぃ、小莉子 提交于 2019-12-21 20:01:11

问题


Snackbars provide lightweight feedback about an operation by showing a brief message at the bottom of the screen. Snackbars can contain an action.

Android also provides a toast, primarily used for system messaging. Toasts are similar to snackbars but do not contain actions and cannot be swiped off screen.

My question

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Toast.makeText(context, "status", Toast.LENGTH_LONG).show();
    }
}

Is it posible to show a Snackbar in a BroadcastReceiver like Toast?


回答1:


is it posible to show snakbars in BroadcastReceiver like Toast?

A BroadcastReceiver registered by an activity or fragment, via registerReceiver(), could ask the activity or fragment to show a snackbar.

A manifest-registered BroadcastReceiver has no UI, and hence it has no place to show a snackbar. What it could do is post an event on an in-process event bus (e.g., LocalBroadcastManager, greenrobot's EventBus, Square's Otto), to let whatever UI of yours that is in the foreground know that a broadcast was received. If the UI layer receives the message, that activity or fragment can show a snackbar. If the event bus event was not picked up, you can perhaps show a Notification as a fallback, if appropriate.




回答2:


As @CommonsWare sir told, there has to be some passing mechanism between BroadcastReceiver and Activity/Fragment where UI is attached.

I have tried to add interface for example here :

public class TestReceiver extends BroadcastReceiver {

    private DoSomethingInterface callback1;

    public TestReceiver() {
    }

    @Override
    public void onReceive(final Context context, final Intent intent) {
        // pass content text to show in SnackBar
        if(callback1 != null) {
            callback1.passText("status");
        } else {
            Log.e("log","callback from UI is not registered yet..");
        }
    }

    public void registerReceiver(DoSomethingInterface receiver) {
         this.callback1 = receiver;
    }

    public interface DoSomethingInterface {
        public void passText(String text);
    }
}

Implement the DoSomethingInterface in your Activity or Fragment where you are showing SnackBar. Make sure that you need to add CoordinatorLayout for displaying SnakeBar :

public class MainActivity extends Activity implements DoSomethingInterface {

public void onCreate() {
    ...
    // pass reference to interface from onCreate()
    BroadcastReceiver mReceiver = new TestReceiver();
    mReceiver.registerReceiver(this);
    ...
}

    @Override
    public void passText(String text) {
        Snackbar.make(<reference to your coordinator layout>, "text", Snackbar.LENGTH_LONG)
                    .setAction("Ok", <listener>)
                    .setActionTextColor(Color.GREEN)
                    .show();



回答3:


my working code....

public abstract  class TestReceiver  extends BroadcastReceiver {
    @Override   
    public void onReceive(final Context context, final Intent intent) {
        onNetworkChange();
    } 

    protected abstract void onNetworkChange();
}

in mainactivity

public class MainActivity extends Activity  {

    public void onCreate() {
        ...  mReceiver = new TestReceiver () {
            @Override
            protected void onNetworkChange() {
            snackbar = Snackbar.make(Clayout, "Please check your internet connection and try again", Snackbar.LENGTH_SHORT);
            snackbar.setAction("X", snackbarClickListener);snackbar.setActionTextColor(Color.GREEN);
            ColoredSnackbar coloredsnakbar=new ColoredSnackbar();
            coloredsnakbar.confirm(snackbar).show();
            }
        };      
    }
}



回答4:


I have a work around, without coding the snackbar in all the activities onCreate() method.

We can use the application class to call the BroadcastReciever. As below code.

public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {
    public static Activity appactivity;
@Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(this);
}
@Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    @Override
    public void onActivityStarted(Activity activity) {

    }

    @Override
    public void onActivityResumed(Activity activity) {
        appactivity = activity;//here we get the activity
        Intent i = new Intent(this, InternetConnectionInformation.class);
        sendBroadcast(i);//here we are calling the broadcastreceiver to check connection state.
    }
}

Now we can use our BroadcastReceiver class to show snackbar as well

public class InternetConnectionInformation extends BroadcastReceiver{
    static Snackbar snackbar; //make it as global
    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager
                = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();

        if (activeNetworkInfo == null || !activeNetworkInfo.isConnected()) {
                InternetConnectionInformation.snack(null, 0, "Network Connection failed.",context.getApplicationContext());
        }else{
            InternetConnectionInformation.hideSnackbar();
        }
    }




    public static void snack (HashMap<String,View.OnClickListener> actions,int priority,String message,Context context) {
     if(MyApplication.appactivity != null){
            snackbar = Snackbar.make(MyApplication.appactivity.findViewById(android.R.id.content), message, Snackbar.LENGTH_INDEFINITE);//MyApplication.appactivity from Application class.
            if (actions != null) {
                Iterator iterator = actions.entrySet().iterator();
                snackbar.setDuration(Snackbar.LENGTH_INDEFINITE);
                while (iterator.hasNext()) {
                    Map.Entry pair = (Map.Entry) iterator.next();
                    snackbar.setAction((String) pair.getKey(), (View.OnClickListener) pair.getValue());
                    iterator.remove(); // avoids a ConcurrentModificationException
                }
            }
            switch (priority) {
                case 0:
                    snackbar.getView().setBackgroundColor(context.getResources().getColor(R.color.accentPink));
                    break;
                case 1:
                    snackbar.getView().setBackgroundColor(Color.parseColor("#66ccff"));
                    break;
                case 2:
                    snackbar.getView().setBackgroundColor(Color.parseColor("#66ff33"));
                    break;
            }
            snackbar.show();
           }
        }
        private static void hideSnackbar(){
            if(snackbar !=null && snackbar.isShown()){
                snackbar.dismiss();
            }
        }
    }

To hide the snackbar we need to check the connectivity state. So the BroadcastReceiver is registered in the Manifest

<receiver android:name="your.package.name.InternetConnectionInformation">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>

This works fine and is tested. Hope it will help some.



来源:https://stackoverflow.com/questions/31428437/how-to-add-snackbars-in-a-broadcastreceiver

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!