Java 内容提供商安卓手机铃声
我想将资产文件夹中的铃声设置为默认铃声。现在我发现,这是不可能的,因为资产不能从外部访问。因此,我必须将文件从我的资产复制到sd,否则我将使用内容提供商。最后我认为是更好的方法 但我没办法,我希望你能帮我。这是我的内容提供商:Java 内容提供商安卓手机铃声,java,android,commonsware-cwac,Java,Android,Commonsware Cwac,我想将资产文件夹中的铃声设置为默认铃声。现在我发现,这是不可能的,因为资产不能从外部访问。因此,我必须将文件从我的资产复制到sd,否则我将使用内容提供商。最后我认为是更好的方法 但我没办法,我希望你能帮我。这是我的内容提供商: public class ringtoneContentProvider extends ContentProvider { private static final String TAG = "ringtoneCP"; private static St
public class ringtoneContentProvider extends ContentProvider {
private static final String TAG = "ringtoneCP";
private static String[] mimeTypes = {"audio/ogg"};
private Uri generatedUri;
@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
Log.d("provider", "Provider openAssetFile wird aufgerufen");
AssetManager am = getContext().getAssets();
String file_name = uri.getLastPathSegment();
if(file_name == null)
throw new FileNotFoundException();
AssetFileDescriptor afd = null;
try {
afd = am.openFd(file_name);
} catch (IOException e) {
e.printStackTrace();
}
return afd;//super.openAssetFile(uri, mode);
}
@Override
public String getType( Uri p1 )
{
Log.d("provider","provider getType");
// TODO: Implement this method
return "audio/ogg";
}
@Override
public int delete( Uri p1, String p2, String[] p3 )
{
// TODO: Implement this method
throw new RuntimeException("ContentProvider.delete not supported");
}
@Override
public Cursor query( Uri p1, String[] p2, String p3, String[] p4, String p5 )
{
Log.d("provider","provider query 1");
// TODO: Implement this method
return null;
}
@Override
public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal )
{
Log.d("provider","provider query 2");
// TODO: Implement this method
return super.query( uri, projection, selection, selectionArgs, sortOrder, cancellationSignal );
}
@Override
public Uri insert( Uri p1, ContentValues p2 )
{
Log.d("provider","provider insert");
// TODO: Implement this method
return null;
}
@Override
public boolean onCreate( )
{
Log.d("provider","provider onCreate");
generatedUri = Uri.EMPTY;
return true;
}
@Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
Log.d("provider","provider getStreamTypes");
return mimeTypes;
}
@Override
public int update( Uri p1, ContentValues p2, String p3, String[] p4 )
{
Log.d("provider","provider update");
// TODO: Implement this method
return 0;
}
}
A我想在这里设置铃声:
RingtoneManager.setActualDefaultRingtoneUri(
getApplicationContext(),
RingtoneManager.TYPE_RINGTONE,
Uri.parse("content://com.xyz.ringtoneContentProvider/ringtone.ogg")
);
但这不起作用。所以我这样做:
Uri myFile = Uri.parse("content://com.xyz.ringtoneContentProvider/ringtone.ogg");
//We now create a new content values object to store all the information
//about the ringtone.
ContentValues values = new ContentValues();
//values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
values.put(MediaStore.MediaColumns.DATA, myFile.getPath());
values.put(MediaStore.MediaColumns.TITLE, "MyRingtone"); // file.getName());
//values.put(MediaStore.MediaColumns.SIZE, file.length());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
values.put(MediaStore.Audio.AudioColumns.ARTIST, getApplicationContext().getString(R.string.app_name));
values.put(MediaStore.Audio.AudioColumns.IS_RINGTONE, true);
values.put(MediaStore.Audio.AudioColumns.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.AudioColumns.IS_ALARM, false);
values.put(MediaStore.Audio.AudioColumns.IS_MUSIC, false);
//Work with the content resolver now
//First get the file we may have added previously and delete it,
//otherwise we will fill up the ringtone manager with a bunch of copies over time.
Uri uri = MediaStore.Audio.Media.getContentUriForPath(myFile.toString());
getApplicationContext().getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + myFile + "\"", null);
//Ok now insert it
Uri newUri = getApplicationContext().getContentResolver().insert(myFile, values);
//Ok now set the ringtone from the content manager's uri, NOT the file's uri
RingtoneManager.setActualDefaultRingtoneUri(
getApplicationContext(),
RingtoneManager.TYPE_RINGTONE,
newUri
);
但这也不起作用
-------------使用流提供程序------------- 使用Steam Provider,如果打开设置应用程序/声音,我会出现以下错误:
The exact Error Message is: Writing exception to parcel
java.lang.SecurityException: Permission Denial: reading com.commonsware.cwac.provider.StreamProvider uri content://com.xyz.myStreamProvider/ringtone.ogg from pid=1446, uid=1000 requires the provider be exported, or grantUriPermission()
at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:467)
at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:394)
at android.content.ContentProvider$Transport.query(ContentProvider.java:194)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112)
at android.os.Binder.execTransact(Binder.java:404)
at dalvik.system.NativeStart.run(Native Method)
如果我执行android:exported=“true”和android:grantUriPermissions=“true”操作,我会收到以下错误消息:
FATAL EXCEPTION: main
Process: com.xyz.app, PID: 1515
java.lang.RuntimeException: Unable to get provider com.commonsware.cwac.provider.StreamProvider: java.lang.SecurityException: Provider must not be exported
at android.app.ActivityThread.installProvider(ActivityThread.java:4793)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4385)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4325)
at android.app.ActivityThread.access$1500(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.SecurityException: Provider must not be exported
at com.commonsware.cwac.provider.StreamProvider.attachInfo(StreamProvider.java:65)
at android.app.ActivityThread.installProvider(ActivityThread.java:4790)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4385)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4325)
at android.app.ActivityThread.access$1500(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
我能做什么?使用
StreamProvider
(或Android的FileProvider
)无法实现您想要的,因为两者都限于由活动发起流请求的情况,您可以使用标志\u GRANT\u URI\u READ\u PERMISSION
来允许选择性访问内容。欢迎您使用forkStreamProvider
解除此限制
但是,您将遇到一个问题,即媒体播放器倾向于想要一个可查找的流,而这不可能从通过StreamProvider
提供服务的资产获得
你的选择是:
FileProvider
或StreamProvider
,因为由FileProvider
或StreamProvider
提供服务时,可以查找由简单文件支持的流你试过使用吗?它包装了支持库,并为资产提供了
内容://
样式的URI。看起来不错,但我不知道,如何使用它?我不懂演示。好的,我让它运行。但现在我得到了权限错误。首先,我从RingtoneManager得到,提供者将grantUriPermissions设置为true,并导出为true。但是当我这样做的时候,我从提供者那里得到了一个错误,提供者不能被导出。那我该怎么办?你找到解决办法了吗?我面临着几乎相同的问题是和否。不可能从资产文件夹中获取铃声。您必须先将其复制到外部存储器谢谢您的回答!可以使用原始文件夹?@Burner:不,从StreamProvider
及其使用者的角度来看,这与资产没有什么不同。