在相应界面运行adb命令获取当前界面的包名
查看RingtonePickerActivity.java
\packages\providers\MediaProvider\src\com\android\providers\media\RingtonePickerActivity
DialogInterface.OnClickListener mRingtoneClickListener
监听点击事件,具体为记录选择点击位置,并播放相应铃声。
final AlertController.AlertParams p = mAlertParams;
p.mCursor = mCursor;
p.mOnClickListener = mRingtoneClickListener;
p.mLabelColumn = MediaStore.Audio.Media.TITLE;
p.mIsSingleChoice = true;
p.mOnItemSelectedListener = this;
p.mPositiveButtonText = getString(com.android.internal.R.string.ok);
p.mPositiveButtonListener = this;
p.mNegativeButtonText = getString(com.android.internal.R.string.cancel);
p.mPositiveButtonListener = this;
p.mOnPrepareListViewListener = this;
p.mTitle = intent.getCharSequenceExtra(RingtoneManager.EXTRA_RINGTONE_TITLE);
if (p.mTitle == null) {
p.mTitle = getString(com.android.internal.R.string.ringtone_picker_title);
}
在onCreate中这部分类似于可选择的选项集合。
在这个界面中都通过RingtoneManager来进行获取位置等操作
RingtoneManager 的路径:
code\frameworks\base\media\java\android\media\RingtoneManager.java
RingtoneManager中获取游标的方法
public Cursor getCursor() {
if (mCursor != null && mCursor.requery()) {
return mCursor;
}
final Cursor internalCursor = getInternalRingtones(); // 获取内置铃声游标
final Cursor mediaCursor = getMediaRingtones(); // 获取媒体文件中的铃声游标
return mCursor = new SortCursor(new Cursor[] { internalCursor, mediaCursor },
MediaStore.Audio.Media.DEFAULT_SORT_ORDER); // 通过MediaStore中存储的选择哪种方式获取铃声来获取不同铃声列表的游标
}
private Cursor getInternalRingtones() {
return query(
MediaStore.Audio.Media.INTERNAL_CONTENT_URI, INTERNAL_COLUMNS,
constructBooleanTrueWhereClause(mFilterColumns),
null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
}
private Cursor getMediaRingtones() {
// Get the external media cursor. First check to see if it is mounted.
final String status = Environment.getExternalStorageState();
return (status.equals(Environment.MEDIA_MOUNTED) ||
status.equals(Environment.MEDIA_MOUNTED_READ_ONLY))
? query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS,
constructBooleanTrueWhereClause(mFilterColumns), null,
MediaStore.Audio.Media.DEFAULT_SORT_ORDER)
: null;
}
分别是加载内部铃声和外部铃声
然后调用相应的query方法返回对应的游标
private Cursor query(Uri uri,
String[] projection,
String selection,
String[] selectionArgs,
String sortOrder) {
if (mActivity != null) {
return mActivity.managedQuery(uri, projection, selection, selectionArgs, sortOrder);
} else {
return mContext.getContentResolver().query(uri, projection, selection, selectionArgs,
sortOrder);
}
}
Uri uri,//内容提供者的查询uri
String[] projection//待查询的参数
String selection//查询条件
String[] selectionArgs, // 查询条件参数
String sortOrder // 查询结果的排序方式
MediaStore的路径code\frameworks\base\core\java\android\provider\MediaStore.java
public static final String AUTHORITY = "media";
private static final String CONTENT_AUTHORITY_SLASH = "content://" + AUTHORITY + "/";
public static Uri getContentUri(String volumeName) {
return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
"/audio/media");
}
public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal");
public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external");
因此uri为 content://media/internal/audio/media
private static final String[] INTERNAL_COLUMNS = new String[] {
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
"\"" + MediaStore.Audio.Media.INTERNAL_CONTENT_URI + "\"",
MediaStore.Audio.Media.TITLE_KEY
};
private static final String[] MEDIA_COLUMNS = new String[] {
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
"\"" + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "\"",
MediaStore.Audio.Media.TITLE_KEY
};
查看相应的internal.db数据库,路径在
data/data/com.android.providers.settings./databases下,发现
两条数据,uri不同但是显示的title相同,在
\code\frameworks\base\data\sounds\ringtones
下有相同的两条音频,名称分别为Hydra和hydra,两条都会经过编译进入系统,在Audio.mk文件中
$(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
删去这句代码,重新编译即可。
但是我并没有明白具体原因是怎么解决的。