【发布时间】:2015-06-24 05:34:57
【问题描述】:
我将分享需要更正的异常。我在我的项目中从手机的外部存储器中提取了音乐文件。我尝试将其设置为 Android Alarm 应用程序的默认铃声。每当我设置它时,它就会显示在警报中,但它没有被播放。我猜是因为下面的异常。
E/DatabaseUtils﹕ Writing exception to parcel
java.lang.SecurityException: External path: /storage/sdcard/Maid with the Flaxen Hair.mp3: Neither user 1000 nor current process has android.permission.READ_EXTERNAL_STORAGE.
at android.app.ContextImpl.enforce(ContextImpl.java:1685)
at android.app.ContextImpl.enforceCallingOrSelfPermission(ContextImpl.java:1714)
at com.android.providers.media.MediaProvider.checkAccess(MediaProvider.java:4615)
at com.android.providers.media.MediaProvider.openFileAndEnforcePathPermissionsHelper(MediaProvider.java:4578)
at com.android.providers.media.MediaProvider.openFile(MediaProvider.java:4502)
at android.content.ContentProvider.openFile(ContentProvider.java:1157)
at android.content.ContentProvider$Transport.openFile(ContentProvider.java:300)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:232)
at android.os.Binder.execTransact(Binder.java:404)
at dalvik.system.NativeStart.run(Native Method)
即使我添加了 READ_EXTERNAL_STORAGE 权限并包含 conentProvider 的 grantUriPermission(),此错误仍然存在。
这是清单文件。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ctsprojects.com.alarmapp" >
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"></uses-permission>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".songList"
android:label="@string/title_activity_song_list"
android:exported="true" >
</activity>
<activity
android:name=".NextAlarm"
android:label="@string/title_activity_next_alarm" >
</activity>
</application>
</manifest>
我使用代码设置铃声的活动。就这样吧。。
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Path;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TimePicker;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.Calendar;
public class songList extends Activity {
private String[] mMusicList;
ListView mListView;
String s, path;
String[] pathhh;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_song_list);
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog()
.penaltyDeath().build());
mListView = (ListView) findViewById(R.id.listView);
mMusicList = getMusic();
ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, mMusicList);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
try {
/*playSong(mMusicList[arg2]);*/
path = pathhh[arg2];
s = (String) mListView.getItemAtPosition(arg2);
Log.d("songName", s);
File k = new File(path);
System.out.println(k);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, s);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, k.length());
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
grantUriPermission("android.media.MediaPlayer", uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
Uri newUri = getContentResolver().insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(songList.this, RingtoneManager.TYPE_ALARM, newUri);
} catch (Throwable t) {
}
//Intent a = new Intent(songList.this, NextAlarm.class);
//a.putExtra("song", s);
// startActivity(a);
finish();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_song_list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private String[] getMusic() {
final Cursor mCursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.MediaColumns.TITLE, MediaStore.MediaColumns.DATA, MediaStore.Audio.AudioColumns.ALBUM}, null, null,
"LOWER(" + MediaStore.Audio.Media.TITLE + ") ASC");
int count = mCursor.getCount();
String[] songs = new String[count];
int i = 0;
String[] pathh= new String[count];
if (mCursor.moveToFirst()) {
do {
songs[i] = mCursor.getString(0);
pathh[i] = mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
i++;
} while (mCursor.moveToNext());
}
pathhh = pathh;
mCursor.close();
return songs;
}
}
在上述活动中。我正在从外部 SD 卡中取出歌曲。将它们填充到 listView 中。点击一首歌,我就有了设置默认闹钟铃声的代码。这就是代码的作用。
我有一个列表视图,其中填充了所有歌曲。我的工作是从列表中单击一首歌曲并将其设置为铃声。我需要从 listView 本身获取路径和文件名。有什么办法吗?
【问题讨论】:
-
添加你的清单文件,你在使用 proguard 吗?
-
我已经添加了 Manifest 文件。我没有使用 proguard。
-
@MitBhatt 我在我的代码中做了同样的事情。我可以将其设置为我的默认闹钟铃声。按照我的意愿工作正常。但它不会播放。我收到上述错误。
-
你能展示你的歌曲列表活动吗?
标签: android