RingtoneManager获取铃声uri返回空值的问题

RingtoneManager获取铃声uri返回空值的问题

在android中使用RingtoneManager管理系统铃声,我们可以利用RingtoneManager类提供的方法获取铃声。

但在使用中,往往会出现返回值为空,或者返回一个对象,但对象中的uri为空的问题。

以getRingtone(int position)这个方法为例,可以传入的参数只有int值,SDK上描述,这个position指ringtone在cursor中的位置。起初遇到这个问题的时候,无论我传入什么值,返回的ringtone的属性(包括title和url)都为空。我尝试在网上查找各种资料,无奈都没有此问题的描述。于是无奈之下,只好查阅源码,这才发现其中的玄机。

源码中getRingtone()这个方法有多个重载函数,我们调用的是

 public Ringtone getRingtone(int position) {
        if (mStopPreviousRingtone && mPreviousRingtone != null) {
            mPreviousRingtone.stop();
        }
        
        mPreviousRingtone = getRingtone(mContext, getRingtoneUri(position), inferStreamType());
        return mPreviousRingtone;
    }

可以看到它实际上调用的又是getRingtone(mContext, getRingtoneUri(position), inferStreamType()) 其中,inferStreamType()返回的是铃声的类型,getRingtoneUri(position)是根据传入的position获取对应的uri,先看getRingtone,源码如下:

private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) {
        Log.d(TAG, "getRingtone() ringtoneUri = " + ringtoneUri
                   + ", streamType = " + streamType);
        try {
            final Ringtone r = new Ringtone(context, true);
            if (streamType >= 0) {
                r.setStreamType(streamType);
            }
            r.setUri(ringtoneUri);
            return r;
        } catch (Exception ex) {
            Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex);
        }

        return null;
    }
可以看到,该方法实际上重新new了一个Ringtone,然后传入的了Uri,然后将新的Ringtone返回。既然我们获得的Ringtone的title和uri是空值,那就说明传入的这个ringtoneUri一定是空值,也就是说,getRingtoneUri(int position)返回的是一个空值,那我们再看一下这个方法是怎么写的

  public Uri getRingtoneUri(int position) {
        // use cursor directly instead of requerying it, which could easily
        // cause position to shuffle.
        if (mCursor == null) {
            Log.v(TAG, "mCursor is null");
            return null;
        }

        try {
            if (mCursor.isClosed() || !mCursor.moveToPosition(position)) {
                Log.v(TAG, "mCursor position is wrong");
                return null;
            }
        } catch (IllegalStateException e) {
            Log.v(TAG, "mCursor exception");
            return null;
        }

        return getUriFromCursor(mCursor);
    }

可见,有三种情况都会返回null,那到底会是哪一种呢?好在源码中用三各不同的log进行了区分,抓一下log,可见

03-12 13:33:01.531 19356 19356 V RingtoneManager: mCursor is null

可见,是mCursor值为空,到这里,已经柳暗花明了。这个mCursor是RingtoneManage的一个私有属性,当我们在new 一个RingtoneManager的时候,这个mCursor并没有被赋值,所以我们获取的uri为空值。

问题找到了,该如何解决呢?源码中还有这样一个方法

  public Cursor getCursor() {
        if (mCursor != null && mCursor.requery()) {
            Log.v(TAG, "getCursor with old cursor = " + mCursor);
            return mCursor;
        }
        
        final Cursor internalCursor = getInternalRingtones();
        final Cursor drmCursor = mIncludeDrm ? getDrmRingtones() : null;
        final Cursor mediaCursor = getMediaRingtones();

        mCursor = new SortCursor(new Cursor[] { internalCursor, drmCursor, mediaCursor },
                MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
        Log.v(TAG, "mCursor.hashCode " + mCursor.hashCode());
        Log.v(TAG, "getCursor with new cursor = " + mCursor);
        return mCursor;
    }

此方法对mCursor进行赋值,然后返回。于是,我们可以定义一个Cursor,接受getCursor返回的值,尽管我们不使用这个Cursor,但此时,已经对RingManager的mCursor赋值了,这样,我们获取uri的时候就不会再返回空值了
















  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值