我尝试显示弹出窗口此代码正常工作,下面是android Oreo版本,此问题只出现在Android Oreo中,显示错误
BadTokenException:无法添加窗口 - 令牌null无效;你的活动在运行吗?
我如何解决这个问题?
这是VideoToneView类以获取更多详细信息
<!DOCTYPE html>
<html>
<head>
<title>Look Ma!</title> <!- ------ Here ->
</head>
...
}
这是我的适配器
public class VideoToneView extends FloatingWindowView {
final String TAG = "VideoToneView";
private String mRequirementId;
int [] screen = Util.getScreenSize(getContext());
double maxWidthScale = 0.8;
// view bind
// main status layout
View photoStatusLayout;
View videoStatusLayout;
// child view
VideoView mVideoView;
TextView tvName;
TextView tvPhone;
TextView tvStatus;
TextView tvVideoName;
TextView tvVideoPhone;
ImageView ivUser;
TextView tvProfile;
// variables
AudioManager mAudioManager;
String msisdn;
MediaSource mMediaSource;
int mCurrentRingerMode = -1;
boolean isIncoming;
int mCurrentRingerVolume = -1;
int mCurrentMusicVolume = -1;
boolean wasPlayed;
public VideoToneView(Context context, String requirementId, String msisdn, boolean isIncoming) {
super(context);
if (requirementId == null)
throw new NullPointerException("requirementId can't be null");
this.mRequirementId = requirementId;
this.msisdn = msisdn;
this.mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
this.isIncoming = isIncoming;
this.mCurrentRingerMode = mAudioManager.getRingerMode();
this.mCurrentRingerVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
this.mCurrentMusicVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
}
public void resetCurrentRingerMode(){
try {
if (wasPlayed) {
wasPlayed = false;
mAudioManager.setStreamVolume(AudioManager.STREAM_RING, mCurrentRingerVolume, 0);
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mCurrentMusicVolume, 0);
mAudioManager.setRingerMode(mCurrentRingerMode);
}
}catch (SecurityException se){}
}
@Override
public void dismiss() {
if(mVideoView != null){
mVideoView.stopPlayback();
mVideoView = null;
}
resetCurrentRingerMode();
super.dismiss();
}
@NonNull
@Override
public View onCreateView(LayoutInflater inflater) {
View view = inflater.inflate(R.layout.view_video_tone, null, false);
int w = (int) (screen[0] * maxWidthScale);
int h = w;
View contentView = view.findViewById(R.id.content_view);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(w, RelativeLayout.LayoutParams.WRAP_CONTENT);
contentView.setLayoutParams(params);
// bind view
photoStatusLayout = view.findViewById(R.id.layout_photo_status);
videoStatusLayout = view.findViewById(R.id.layout_video_status);
tvName = view.findViewById(R.id.tv_name);
tvPhone = view.findViewById(R.id.tv_phone);
tvStatus = view.findViewById(R.id.tv_status);
tvVideoName = view.findViewById(R.id.tv_video_name);
tvVideoPhone = view.findViewById(R.id.tv_video_phone);
tvProfile = view.findViewById(R.id.tv_status2);
ivUser = view.findViewById(R.id.iv_user);
// set listener
view.findViewById(R.id.iv_close).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
// show caller profile window
showCallerWindow(view);
return view;
}
private void showCallerWindow(View root){
// own profile
ContactItem own = SessionManager.getProfile(getContext());
// caller contact
ContactItem item = ContactDBManager
.getInstance(getContext())
.getCallerByMSISDN(msisdn);
// video tone is enable
boolean isVideoToneEnable = PreferenceUtil
.getPref(getContext())
.getBoolean(PreferenceUtil.VIDEO_TONE_ENABLE, true);
// show caller profile
tvName.setText(item.getName("Unknown"));
tvPhone.setText(item.msisdn);
tvVideoName.setText(item.getName());
tvVideoPhone.setText(item.msisdn);
Glide.with(getContext())
.load(item.caller_pic)
.apply(RequestOptions.circleCropTransform()
.placeholder(R.drawable.ic_add_profile_grey))
.into(ivUser);
if(isIncoming) {
String profile = "Calling...";
for(ProfileItem.Item i: item.profiles.list){
if(own.msisdn.equalsIgnoreCase(i.msisdn)){
profile = i.profile;
break;
}
else if(TextUtils.isEmpty(i.msisdn)){
profile = i.profile;
}
}
tvStatus.setText(profile); // munculin profile sesuai msisdn
tvProfile.setText(profile); // munculin profile sesuai msisdn
}
else
tvStatus.setText(item.getStatusCaller()); // munculin status orang yang ditelpon
if(!TextUtils.isEmpty(item.video_caller) && isVideoToneEnable && isIncoming){ // show video tone only on incoming call
photoStatusLayout.setVisibility(View.GONE);
videoStatusLayout.setVisibility(View.VISIBLE);
Uri uri = CallerVideoManager.getVideoUri(getContext(), item.video_caller);
initVideoView(root, uri);
}
else{ // show status only
photoStatusLayout.setVisibility(View.VISIBLE);
videoStatusLayout.setVisibility(View.GONE);
}
}
public int[] getXY () {
int screenWidth = screen[0];
int w = (int) (screenWidth * maxWidthScale);
int x = (screenWidth - w) / 2;
//int y = screen[1] / 4;
int y = w / 2;
int size [] = {x, y};
return size;
}
private void initVideoView(View root, final Uri mVideoUri) {
// force ringtone to silent mode
try {
this.mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
catch (SecurityException se){}
// init video caller window
mVideoView = root.findViewById(R.id.video_view);
mVideoView.setOnPreparedListener(new net.protyposis.android.mediaplayer.MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(net.protyposis.android.mediaplayer.MediaPlayer vp) {
vp.setLooping(true);
}
});
mVideoView.setOnErrorListener(new net.protyposis.android.mediaplayer.MediaPlayer.OnErrorListener() {
@Override
public boolean onError(net.protyposis.android.mediaplayer.MediaPlayer mp, int what, int extra) {
photoStatusLayout.setVisibility(View.VISIBLE);
videoStatusLayout.setVisibility(View.GONE);
return true;
}
});
Utils.MediaSourceAsyncCallbackHandler mMediaSourceAsyncCallbackHandler =
new Utils.MediaSourceAsyncCallbackHandler() {
@Override
public void onMediaSourceLoaded(MediaSource mediaSource) {
try {
mMediaSource = mediaSource;
mVideoView.setVideoSource(mediaSource);
mVideoView.setPlaybackSpeed(1);
mVideoView.setZOrderOnTop(true);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
wasPlayed = true;
if(mCurrentRingerVolume > 0){
mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 0, 0 );
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mCurrentRingerVolume, 0 );
}
else{
mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 0, 0 );
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0 );
}
mVideoView.start();
}
}, 500);
}
catch (Exception e){
Log.e(TAG,"error loading video", e);
}
}
@Override
public void onException(Exception e) {
Log.e(TAG, "error loading video", e);
}
};
if(mMediaSource == null) {
// Convert uri to media source asynchronously to avoid UI blocking
// It could take a while, e.g. if it's a DASH source and needs to be preprocessed
Utils.uriToMediaSourceAsync(getContext(), mVideoUri, mMediaSourceAsyncCallbackHandler);
} else {
// Media source is already here, just use it
mMediaSourceAsyncCallbackHandler.onMediaSourceLoaded(mMediaSource);
}
}
public static VideoToneView showDummyFloatingWindow(Context appContext, String msisdn, boolean isIncoming){
VideoToneView view = new VideoToneView(appContext, "R7721", msisdn, isIncoming);
FloatingWindowController fwc = FloatingWindowController.create(appContext);
int[] point = view.getXY();
fwc.showAtLocation(view, Gravity.TOP | Gravity.START, point[0], point[1]);
return view;
}
这里是上面的适配器片段
public class ContactMVICallCursorAdapter extends CursorAdapter {
static final String TAG = "ContactCursorAdapter";
LayoutInflater mInflater;
Activity activity;
public ContactMVICallCursorAdapter(Context context, Cursor c, boolean autoRequery) {
super(context, c, autoRequery);
mInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
final View itemLayout = mInflater.inflate(R.layout.item_contact, viewGroup, false);
final ViewHolder holder = new ViewHolder();
holder.tvUserName = itemLayout.findViewById(R.id.et_user_name);
holder.tvUserStatus = itemLayout.findViewById(R.id.tv_user_status);
holder.ivUserPic = itemLayout.findViewById(R.id.iv_user);
holder.ivPhone = itemLayout.findViewById(R.id.iv_phone);
itemLayout.setTag(holder);
return itemLayout;
}
@Override
public void bindView(View view, final Context context, Cursor cursor) {
final ViewHolder holder = (ViewHolder) view.getTag();
final String photoUri = cursor.getString(cursor.getColumnIndex(UserTable.UserEntry.COLUMN_NAME_PIC));
final String displayName = cursor.getString(cursor.getColumnIndex(UserTable.UserEntry.COLUMN_NAME_NAME));
final String msisdn = cursor.getString(cursor.getColumnIndex(UserTable.UserEntry.COLUMN_NAME_MSISDN));
final String status = cursor.getString(cursor.getColumnIndex(UserTable.UserEntry.COLUMN_NAME_STATUS));
holder.tvUserName.setText(displayName.isEmpty()?msisdn:displayName);
holder.tvUserStatus.setText(TextUtils.isEmpty(status)?"'No Status'":status);
Glide.with(context)
.load(photoUri)
.apply(RequestOptions.circleCropTransform()
.placeholder(R.drawable.ic_add_profile_grey))
.into(holder.ivUserPic);
holder.ivPhone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
call(view.getContext(), msisdn);
}
});
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(videoToneView != null){
videoToneView.dismiss();
videoToneView = null;
}
VideoToneView.showDummyFloatingWindow(view.getContext().getApplicationContext(), msisdn, true);
}
});
}
private void call(Context ctx, String number){
Intent phoneIntent = new Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", number, null));
ctx.startActivity(phoneIntent);
}
private class ViewHolder {
TextView tvUserName;
TextView tvUserStatus;
ImageView ivUserPic;
ImageView ivPhone;
}
// DUMMY
VideoToneView videoToneView;
}
}
答案 0 :(得分:0)
您的最终代码将如下:
static final String TAG = "ContactCursorAdapter";
LayoutInflater mInflater;
Activity activity;
Context mContext;
public ContactMVICallCursorAdapter(Context context, Cursor c, boolean autoRequery) {
super(context, c, autoRequery);
this.mContext=context;
mInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
final View itemLayout = mInflater.inflate(R.layout.item_contact, viewGroup, false);
final ViewHolder holder = new ViewHolder();
holder.tvUserName = itemLayout.findViewById(R.id.et_user_name);
holder.tvUserStatus = itemLayout.findViewById(R.id.tv_user_status);
holder.ivUserPic = itemLayout.findViewById(R.id.iv_user);
holder.ivPhone = itemLayout.findViewById(R.id.iv_phone);
itemLayout.setTag(holder);
return itemLayout;
}
@Override
public void bindView(View view, final Context context, Cursor cursor) {
final ViewHolder holder = (ViewHolder) view.getTag();
final String photoUri = cursor.getString(cursor.getColumnIndex(UserTable.UserEntry.COLUMN_NAME_PIC));
final String displayName = cursor.getString(cursor.getColumnIndex(UserTable.UserEntry.COLUMN_NAME_NAME));
final String msisdn = cursor.getString(cursor.getColumnIndex(UserTable.UserEntry.COLUMN_NAME_MSISDN));
final String status = cursor.getString(cursor.getColumnIndex(UserTable.UserEntry.COLUMN_NAME_STATUS));
holder.tvUserName.setText(displayName.isEmpty()?msisdn:displayName);
holder.tvUserStatus.setText(TextUtils.isEmpty(status)?"'No Status'":status);
Glide.with(context)
.load(photoUri)
.apply(RequestOptions.circleCropTransform()
.placeholder(R.drawable.ic_add_profile_grey))
.into(holder.ivUserPic);
holder.ivPhone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
call(view.getContext(), msisdn);
}
});
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(videoToneView != null){
videoToneView.dismiss();
videoToneView = null;
}
if (!((YourMainActivityName)mContext).isFinishing()) {
videoToneView.showDummyFloatingWindow(mContext, msisdn, true); }
}
});
}
private void call(Context ctx, String number){
Intent phoneIntent = new Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", number, null));
ctx.startActivity(phoneIntent);
}
private class ViewHolder {
TextView tvUserName;
TextView tvUserStatus;
ImageView ivUserPic;
ImageView ivPhone;
}
// DUMMY
VideoToneView videoToneView;
}