diff --git a/README.md b/README.md index 33f50de..36dca73 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,17 @@ [![Build Status](https://travis-ci.org/grandcentrix/tray.svg?branch=master)](https://travis-ci.org/grandcentrix/tray) [![License](https://img.shields.io/badge/license-Apache%202-green.svg?style=flat)](https://github.com/grandcentrix/tray/blob/master/LICENSE.txt) +## Why I fork this? +[grandcentrix/tray](https://github.com/grandcentrix/tray)'s ContentProvider is running in the app main process. But sometimes we (as app developers) may want to have it running in another process (say, ":service" process). So this fork allows you to achieve it, by add below into app manifest: +``` + + +``` + +--- If you have read the documentation of the [`SharedPreferences`](http://developer.android.com/reference/android/content/SharedPreferences.html) you might have seen one of these warnings: >Note: currently this class does not support use across multiple processes. This will be added later. diff --git a/library/src/androidTest/java/net/grandcentrix/tray/provider/TrayContractTest.java b/library/src/androidTest/java/net/grandcentrix/tray/provider/TrayContractTest.java index 0dd0229..cb5a8df 100644 --- a/library/src/androidTest/java/net/grandcentrix/tray/provider/TrayContractTest.java +++ b/library/src/androidTest/java/net/grandcentrix/tray/provider/TrayContractTest.java @@ -65,6 +65,30 @@ public void testGenerateInternalContentUri_WithCorrectProvider_ShouldWork() assertEquals("my.custom.authority", TrayContract.sAuthority); } + + public void testGenerateInternalContentUri_WithNameNotFoundExp_AppShouldCrash(){ + final List mockProviders = new ArrayList<>(); + + ProviderInfo wrongInfo = new ProviderInfo(); + wrongInfo.authority = "wrong"; + wrongInfo.name = "wrong"; + mockProviders.add(wrongInfo); + + ProviderInfo info = new ProviderInfo(); + info.authority = "my.custom.authority"; + info.name = TrayContentProvider.class.getName(); + mockProviders.add(info); + + getProviderMockContext().setProviderInfos(mockProviders); + getProviderMockContext().setThrowNameNotFoundFromPackageManager(true); + + try { + TrayContract.generateInternalContentUri(getProviderMockContext()); + fail("did not throw"); + } catch (TrayRuntimeException e) { + assertTrue(e.getMessage().contains("Internal tray error")); + } + } public void testGenerateInternalContentUri_WithWrongProviders_AppShouldCrash() throws Exception { diff --git a/library/src/androidTest/java/net/grandcentrix/tray/provider/TrayProviderTestCase.java b/library/src/androidTest/java/net/grandcentrix/tray/provider/TrayProviderTestCase.java index 7eb416c..1ce2cf0 100644 --- a/library/src/androidTest/java/net/grandcentrix/tray/provider/TrayProviderTestCase.java +++ b/library/src/androidTest/java/net/grandcentrix/tray/provider/TrayProviderTestCase.java @@ -24,6 +24,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.res.Resources; @@ -47,6 +48,8 @@ public abstract class TrayProviderTestCase extends ProviderTestCase2 mProviderInfos; @@ -73,6 +76,10 @@ public void enableMockResolver(final boolean enabled) { mHasMockResolver = enabled; } + public void setThrowNameNotFoundFromPackageManager(final boolean shouldThrow){ + mThrowNameNotFoundFromPm = shouldThrow; + } + @Override public Context getApplicationContext() { return innerContext; @@ -121,6 +128,18 @@ public List queryContentProviders(final String processName, final int uid, final int flags) { return mProviderInfos; } + + @Override + public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { + if(mThrowNameNotFoundFromPm) throw new NameNotFoundException(); + else { + final PackageInfo pkgInfo = new PackageInfo(); + if (null != mProviderInfos) { + pkgInfo.providers = mProviderInfos.toArray(new ProviderInfo[mProviderInfos.size()]); + } + return pkgInfo; + } + } }; } diff --git a/library/src/main/java/net/grandcentrix/tray/provider/TrayContract.java b/library/src/main/java/net/grandcentrix/tray/provider/TrayContract.java index eb33c4b..2e64cf4 100644 --- a/library/src/main/java/net/grandcentrix/tray/provider/TrayContract.java +++ b/library/src/main/java/net/grandcentrix/tray/provider/TrayContract.java @@ -21,16 +21,15 @@ import net.grandcentrix.tray.core.TrayRuntimeException; import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.net.Uri; -import android.os.Process; import android.provider.BaseColumns; import android.support.annotation.NonNull; import android.support.annotation.VisibleForTesting; import android.util.Log; -import java.util.List; - /** * Contract defining the data in the {@link TrayContentProvider}. Use {@link TrayProviderHelper} to * access them. @@ -120,20 +119,23 @@ private static synchronized String getAuthority(@NonNull final Context context) } checkOldWayToSetAuthority(context); - - // read all providers of the app and find the TrayContentProvider to read the authority - final List providers = context.getPackageManager() - .queryContentProviders(context.getPackageName(), Process.myUid(), 0); - if (providers != null) { - for (ProviderInfo provider : providers) { - if (provider.name.equals(TrayContentProvider.class.getName())) { - sAuthority = provider.authority; - TrayLog.v("found authority: " + sAuthority); - return sAuthority; + + try { + final PackageInfo pkgInfo = context.getPackageManager() + .getPackageInfo(context.getPackageName(), PackageManager.GET_PROVIDERS); + if(null != pkgInfo.providers){ + for (ProviderInfo provider : pkgInfo.providers) { + if (provider.name.equals(TrayContentProvider.class.getName())) { + sAuthority = provider.authority; + TrayLog.v("found authority: " + sAuthority); + return sAuthority; + } } } + } catch (final PackageManager.NameNotFoundException e) { + Log.e("Tray", "Unable to get PackageInfo of current package " + context.getPackageName(), e); } - + // Should never happen. Otherwise we implemented tray in a wrong way! throw new TrayRuntimeException("Internal tray error. " + "Could not find the provider authority. "