Android 'Unable to add window — token null is not for an application' 异常
Android 'Unable to add window — token null is not for an application' exception
我正在尝试为网络变化实施观察者模式。我大致了解这是如何工作的,需要一些微调帮助,因为在尝试通知用户他们已失去连接时,我收到以下错误:
Android 'Unable to add window — token null is not for an application' 异常
这是我的设置。首先,我有一个扩展 BroadcastReceiver 的 ConnectionReceiver class。
public class ConnectionReceiver extends BroadcastReceiver {
private static final String TAG = ConnectionReceiver.class.getSimpleName();
private final List<NetworkStatusObserver> mObserverList = new ArrayList<NetworkStatusObserver>();
private static boolean isNetworkConnected = true;
@Override
public void onReceive(Context context, Intent intent) {
Logger.i(TAG, "onReceive() broadcast");
boolean disconnected = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
boolean isNetworkConnectedCurrent;
if (disconnected) {
isNetworkConnectedCurrent = false;
} else {
NetworkInfo networkInfo;
if (Build.VERSION.SDK_INT < 17) {
networkInfo = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
} else {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
int networkType = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 0);
networkInfo = cm.getNetworkInfo(networkType);
}
if (networkInfo != null && networkInfo.isConnected()) {
isNetworkConnectedCurrent = true;
} else {
isNetworkConnectedCurrent = false;
}
}
if (isNetworkConnectedCurrent != isNetworkConnected) {
isNetworkConnected = isNetworkConnectedCurrent;
Logger.d(TAG, "NetworkStatus.onReceive - isNetworkConnected: " + isNetworkConnected);
notifyObservers(isNetworkConnected);
}
if (isNetworkConnected) {
// already connected
} else {
Utils.showDialog(context, "", context.getString(R.string.default_network_error_message), false,
context.getString(R.string.retry), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// handle click action
}
});
}
}
/**
* Lets all {@link NetworkStatusObserver}s know if the device is connected to a network.
*
* @param isNetworkConnectedCurrent
*/
private void notifyObservers(Boolean isNetworkConnectedCurrent) {
for (NetworkStatusObserver networkStatusObserver : mObserverList) {
networkStatusObserver.notifyConnectionChange(isNetworkConnectedCurrent);
}
}
public void addObserver(NetworkStatusObserver observer) {
mObserverList.add(observer);
}
public void removeObserver(NetworkStatusObserver observer) {
mObserverList.remove(observer);
}
/**
* Interface for monitoring network status change
*/
public interface NetworkStatusObserver {
void notifyConnectionChange(boolean isConnected);
}
我在Utils.java中调用的对话框方法是
public static void showDialog(Context context, String title, String message, boolean cancelable, String buttonLabel, DialogInterface.OnClickListener buttonListener) {
if (isDialogShowing()) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title)
.setMessage(message)
.setCancelable(cancelable)
.setNeutralButton(buttonLabel, buttonListener);
mDialog = builder.create();
mDialog.show(); // <--- the error comes on this line
}
我在清单中注册了这个接收器
<receiver android:name=".network.ConnectionReceiver">
<intent-filter >
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
问题是我将应用程序上下文传递给对话框而不是 Activity 对话框。因此,我删除了广播接收器中调用对话框的代码部分,并尝试将其添加到我的 MainActivity.java class 中。我实现了 NetworkStatusObserver,但在这样做时我收到
的错误
notifyConnectionChange 无法解析
我不确定观察者应该如何发生。顺便说一句,MainActivity extends FragmentActivity 这让我很难在 onPause() 和 onResume() 中 add/remove 我的观察者,因为我不确定用什么来代替"this"。 "this" 应该是什么?
// Note: connectionStatusReceiver is an object of ConnectionReceiver
unregisterReceiver(connectionStatusReceiver );
connectionStatusReceiver.removeObserver(this);
并在我的 onResume() 中尝试添加
connectionStatusReceiver.addObserver(this);
registerReceiver(connectionStatusReceiver , new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
我找到了问题的答案。我无法从我的广播接收器启动对话,因为我将应用程序上下文而不是 Activity 上下文传递给我的对话。解决方案是在我希望监视网络更改的片段和活动上实现 NetworkStatusObserver 接口。在这样做的同时,我必须记住注册和取消注册我的接收器。对于 Activites,我在 onResume()/onPause() 中注册和注销了我的接收器,对于片段,我在 onStart()/onPause() 中注册和注销了我的接收器。
下面是我显示对话框的方式。
@Override
public void notifyConnectionChange(boolean isConnected) {
Logger.i(TAG, "notifyConnectionChange: " + isConnected);
if (isConnected && DeviceUtils.isNetworkAvailable(getActivity().getApplicationContext()) &&
DialogUtils.isDialogShowing()) {
DialogUtils.dismissDialog();
} else {
DialogUtils.showDialog(getActivity().getApplicationContext(), "",
getString(R.string.default_network_error_message), false,
getString(R.string.retry), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (DeviceUtils.isNetworkAvailable(getActivity().getApplicationContext())) {
DialogUtils.dismissDialog();
}
}
});
}
}
希望这能帮助对如何使用观察者模式有类似误解的人。干杯!
在 showDialog()
中传递 YourActivity.this
对象而不是 Context
喜欢
public static void showDialog(Acitivity activity, String title, String message, boolean cancelable, String buttonLabel, DialogInterface.OnClickListener buttonListener) {
if (isDialogShowing()) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(title)
.setMessage(message)
.setCancelable(cancelable)
.setNeutralButton(buttonLabel, buttonListener);
mDialog = builder.create();
mDialog.show(); // <--- the error comes on this line
}
你可以看到这个Link for Reference:
我正在尝试为网络变化实施观察者模式。我大致了解这是如何工作的,需要一些微调帮助,因为在尝试通知用户他们已失去连接时,我收到以下错误:
Android 'Unable to add window — token null is not for an application' 异常
这是我的设置。首先,我有一个扩展 BroadcastReceiver 的 ConnectionReceiver class。
public class ConnectionReceiver extends BroadcastReceiver {
private static final String TAG = ConnectionReceiver.class.getSimpleName();
private final List<NetworkStatusObserver> mObserverList = new ArrayList<NetworkStatusObserver>();
private static boolean isNetworkConnected = true;
@Override
public void onReceive(Context context, Intent intent) {
Logger.i(TAG, "onReceive() broadcast");
boolean disconnected = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
boolean isNetworkConnectedCurrent;
if (disconnected) {
isNetworkConnectedCurrent = false;
} else {
NetworkInfo networkInfo;
if (Build.VERSION.SDK_INT < 17) {
networkInfo = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
} else {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
int networkType = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 0);
networkInfo = cm.getNetworkInfo(networkType);
}
if (networkInfo != null && networkInfo.isConnected()) {
isNetworkConnectedCurrent = true;
} else {
isNetworkConnectedCurrent = false;
}
}
if (isNetworkConnectedCurrent != isNetworkConnected) {
isNetworkConnected = isNetworkConnectedCurrent;
Logger.d(TAG, "NetworkStatus.onReceive - isNetworkConnected: " + isNetworkConnected);
notifyObservers(isNetworkConnected);
}
if (isNetworkConnected) {
// already connected
} else {
Utils.showDialog(context, "", context.getString(R.string.default_network_error_message), false,
context.getString(R.string.retry), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// handle click action
}
});
}
}
/**
* Lets all {@link NetworkStatusObserver}s know if the device is connected to a network.
*
* @param isNetworkConnectedCurrent
*/
private void notifyObservers(Boolean isNetworkConnectedCurrent) {
for (NetworkStatusObserver networkStatusObserver : mObserverList) {
networkStatusObserver.notifyConnectionChange(isNetworkConnectedCurrent);
}
}
public void addObserver(NetworkStatusObserver observer) {
mObserverList.add(observer);
}
public void removeObserver(NetworkStatusObserver observer) {
mObserverList.remove(observer);
}
/**
* Interface for monitoring network status change
*/
public interface NetworkStatusObserver {
void notifyConnectionChange(boolean isConnected);
}
我在Utils.java中调用的对话框方法是
public static void showDialog(Context context, String title, String message, boolean cancelable, String buttonLabel, DialogInterface.OnClickListener buttonListener) {
if (isDialogShowing()) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title)
.setMessage(message)
.setCancelable(cancelable)
.setNeutralButton(buttonLabel, buttonListener);
mDialog = builder.create();
mDialog.show(); // <--- the error comes on this line
}
我在清单中注册了这个接收器
<receiver android:name=".network.ConnectionReceiver">
<intent-filter >
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
问题是我将应用程序上下文传递给对话框而不是 Activity 对话框。因此,我删除了广播接收器中调用对话框的代码部分,并尝试将其添加到我的 MainActivity.java class 中。我实现了 NetworkStatusObserver,但在这样做时我收到
的错误notifyConnectionChange 无法解析
我不确定观察者应该如何发生。顺便说一句,MainActivity extends FragmentActivity 这让我很难在 onPause() 和 onResume() 中 add/remove 我的观察者,因为我不确定用什么来代替"this"。 "this" 应该是什么?
// Note: connectionStatusReceiver is an object of ConnectionReceiver
unregisterReceiver(connectionStatusReceiver );
connectionStatusReceiver.removeObserver(this);
并在我的 onResume() 中尝试添加
connectionStatusReceiver.addObserver(this);
registerReceiver(connectionStatusReceiver , new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
我找到了问题的答案。我无法从我的广播接收器启动对话,因为我将应用程序上下文而不是 Activity 上下文传递给我的对话。解决方案是在我希望监视网络更改的片段和活动上实现 NetworkStatusObserver 接口。在这样做的同时,我必须记住注册和取消注册我的接收器。对于 Activites,我在 onResume()/onPause() 中注册和注销了我的接收器,对于片段,我在 onStart()/onPause() 中注册和注销了我的接收器。
下面是我显示对话框的方式。
@Override
public void notifyConnectionChange(boolean isConnected) {
Logger.i(TAG, "notifyConnectionChange: " + isConnected);
if (isConnected && DeviceUtils.isNetworkAvailable(getActivity().getApplicationContext()) &&
DialogUtils.isDialogShowing()) {
DialogUtils.dismissDialog();
} else {
DialogUtils.showDialog(getActivity().getApplicationContext(), "",
getString(R.string.default_network_error_message), false,
getString(R.string.retry), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (DeviceUtils.isNetworkAvailable(getActivity().getApplicationContext())) {
DialogUtils.dismissDialog();
}
}
});
}
}
希望这能帮助对如何使用观察者模式有类似误解的人。干杯!
在 showDialog()
YourActivity.this
对象而不是 Context
喜欢
public static void showDialog(Acitivity activity, String title, String message, boolean cancelable, String buttonLabel, DialogInterface.OnClickListener buttonListener) {
if (isDialogShowing()) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(title)
.setMessage(message)
.setCancelable(cancelable)
.setNeutralButton(buttonLabel, buttonListener);
mDialog = builder.create();
mDialog.show(); // <--- the error comes on this line
}
你可以看到这个Link for Reference: