在android Oreo上显示弹出窗口时出现BadTokenException

时间:2018-04-04 04:38:09

标签: android popupwindow

我尝试显示弹出窗口此代码正常工作,下面是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;
}

}

1 个答案:

答案 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;
}