问题
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