我无法弄清楚为什么需要实现内容提供者和/或内容信息以及如何实现。我已经阅读了几本不同的文章,却没有找到结论或解决方案。
该应用程序是为Android TV(API 27)制作的,基于WebView,HttpURLConnection和ExoPlayer。 WebView和ExoPlayer使用缓存,但是即使我确保它们不使用缓存,该错误仍然会发生。我也找不到URL和WebView,HttpURLConnection和ExoPlayer与错误之间的链接。
那为什么我会得到这个错误以及如何消除它呢?
错误:
2019-03-06 21:55:17.102 2105-2105/com.google.android.tvlauncher E/PrtnrWidgetInfoLdr: Exception in onStartLoading() on registering content observer
java.lang.SecurityException: Failed to find provider tvlauncher.widget for user 0; expected to find a valid ContentProvider for this authority
at android.os.Parcel.readException(Parcel.java:2004)
at android.os.Parcel.readException(Parcel.java:1950)
at android.content.IContentService$Stub$Proxy.registerContentObserver(IContentService.java:768)
at android.content.ContentResolver.registerContentObserver(ContentResolver.java:1924)
at android.content.ContentResolver.registerContentObserver(ContentResolver.java:1913)
at com.google.android.tvlauncher.data.PartnerWidgetInfoLoader.onStartLoading(PartnerWidgetInfoLoader.java:66)
at android.content.Loader.startLoading(Loader.java:290)
at android.app.LoaderManagerImpl$LoaderInfo.start(LoaderManager.java:283)
at android.app.LoaderManagerImpl.doStart(LoaderManager.java:783)
at android.app.Fragment.onStart(Fragment.java:1631)
at com.google.android.tvlauncher.home.HomeFragment.onStart(HomeFragment.java:239)
at android.app.Fragment.performStart(Fragment.java:2534)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1315)
at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1557)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1618)
at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3027)
at android.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:2984)
at android.app.FragmentController.dispatchStart(FragmentController.java:189)
at android.app.Activity.performStart(Activity.java:7035)
at android.app.Activity.performRestart(Activity.java:7104)
at android.app.Activity.performResume(Activity.java:7109)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1638)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
2019-03-06 21:55:17.106 2105-32408/com.google.android.tvlauncher E/ActivityThread: Failed to find provider info for tvlauncher.widget
可能相关的代码部分:
主要活动:
public class DTV extends Activity {
private final String url = "a https url";
[...]
// Setup WebView and load the content
private void loadDTVapp() {
WebSettings dtvAppViewSettings = dtvAppView.getSettings();
[...]
// Enable cache
dtvAppViewSettings.setAppCachePath(this.getCacheDir().getAbsolutePath());
dtvAppViewSettings.setAppCacheEnabled(true);
dtvAppViewSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
[...]
// Set origin policy
dtvAppViewSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
// Enable JavaScript support
dtvAppViewSettings.setJavaScriptEnabled(true);
// Implement some missing features
dtvAppView.addJavascriptInterface(new extendJSInterface(), "DTV"); // showPlayer and onCloseApp
dtvAppView.setWebViewClient(new WebClient()); // Remaining implementations (Loading icon, injection etc)
// Getting/load/start the DTV HTTP app
dtvAppView.loadUrl(url);
[...]
private class WebClient extends WebViewClient {
[...]
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
[...]
// Adapt main content
if (_url.equals(url)) {
[...]
// Create connection
HttpURLConnection conn = (HttpURLConnection) new URL(_url).openConnection();
try {
if (conn.getResponseCode() == 200) {
// Get encoding
String encoding = "utf-8";
String[] contentTypeParts = conn.getContentType().split(";\\s*charset\\s*=");
if (contentTypeParts.length > 1) {
encoding = contentTypeParts[1];
}
// Read content and inject js
String content = injection(readStream(conn.getInputStream(), encoding));
// Headers
Map<String, String> headers = new HashMap<>();
for (Map.Entry<String, List<String>> entries : conn.getHeaderFields().entrySet()) {
if (entries.getKey() == null) {
headers.put("Status-Code-Originally", entries.getValue().get(0));
} else if (entries.getKey().equalsIgnoreCase("client-via")) {
headers.put("Client-Via-Originally", entries.getValue().get(0));
} else if (entries.getKey().equalsIgnoreCase("content-type")) {
headers.put("Content-Type-Originally", entries.getValue().get(0));
} else if (entries.getKey().equalsIgnoreCase("content-length")) {
headers.put("Content-Length-Originally", entries.getValue().get(0));
} else {
headers.put(entries.getKey(), entries.getValue().get(0));
}
}
// Return new response
return new WebResourceResponse("text/html", encoding, 200, "OK", headers,
new ByteArrayInputStream(content.getBytes(encoding)));
}
} finally {
conn.disconnect();
}
[...]
玩家活动:
public class DTVPlayer extends Activity {
[...]
@Override
protected void onCreate(Bundle savedInstanceState) {
[...]
defaultMediaSource = new ExtractorMediaSource.Factory(
new CacheDataSourceFactory(
VideoCache.getInstance(this),
new DefaultHttpDataSourceFactory(userAgent)));
[...]
class VideoCache {
private static SimpleCache sDownloadCache;
static SimpleCache getInstance(Context context) {
if (sDownloadCache == null) {
sDownloadCache = new SimpleCache(
new File(context.getCacheDir(), "video_cache"),
new LeastRecentlyUsedCacheEvictor(25*1024*1024)
);
}
return sDownloadCache;
}
}