1

I have a "data hub" that contains a ContentProvider that I wish to access from other external apps. I have so far succeeded in setting up the required permissions and contract classes to access the data through a ContentResolver, which works well enough as long as the data hub app is still running. If I close the data hub, it seems the ContentResolver closes with it (e.g. CursorLoader.LoadInBackgroundv returns null). So I'll trying to find a way to keep the provider active even when the owning app closes. My initial thought is to just run the provider in a remote process Service, but I'm having trouble finding any concrete implementations and I'm too new at this to trust my intuition and burn through my battery. As I understand it this is a fairly common use case scenario, so does anyone know how to make the ContentProvider work for external apps even when the main app has been closed?

Edit

Below is the code that I am having trouble with. When the app containing the ContentProvider is running, cursor is loaded. Otherwise, it is null. So to restate the question, do I need to keep the ContentProvider's app running, or can I move the provider into a separate, remote process which remains running even when its app is closed?

    private IReadOnlyCollection<ITranslationData> ReadTranslations(string selection, string[] selectionArgs)
    {
        var uri = TranslationConstants.ContentUri;
        string[] projection =
        {
            TranslationConstants.Id,
            TranslationConstants.Name,
            TranslationConstants.Abbrev,
            TranslationConstants.Info,
            TranslationConstants.OsisUrl
        };

        var loader = new CursorLoader(this.context, uri, projection, selection, selectionArgs, TranslationConstants.Abbrev);
        var cursor = loader.LoadInBackground() as ICursor;

        var translations = new List<ITranslationData>();
        if (cursor.MoveToFirst())
        {
            var hasData = true;
            while (hasData)
            {
                translations.Add(new TranslationData(
                    cursor.GetInt(cursor.GetColumnIndex(TranslationConstants.Id)),
                    cursor.GetString(cursor.GetColumnIndex(TranslationConstants.Name)),
                    cursor.GetString(cursor.GetColumnIndex(TranslationConstants.Abbrev)),
                    cursor.GetString(cursor.GetColumnIndex(TranslationConstants.Info)),
                    cursor.GetString(cursor.GetColumnIndex(TranslationConstants.OsisUrl))));

                hasData = cursor.MoveToNext();
            }
        }

        return translations.AsReadOnly();
    }
Community
  • 1
  • 1
Bondolin
  • 2,793
  • 7
  • 34
  • 62
  • 2
    "As I understand it this is a fairly common use case scenario" -- um, no. "so does anyone know how to make the ContentProvider work for external apps even when the main app has been closed?" -- it does automatically. When another app attempts to use your provider, if you do not have a process running, Android will fork a process for you. However, once nothing is using your provider actively, Android will terminate your process if you are in the background. Beyond that, provide a [mcve] explaining what "the ContentResolver closes with it" means. – CommonsWare Feb 17 '18 at 18:52
  • @CommonsWare, edited with the relevant code. – Bondolin Feb 20 '18 at 03:02
  • 1
    That's not how you use a `CursorLoader`. You do not call `loadInBackground()` yourself; that is for the framework to use. If you are going to use `CursorLoader`, please [read the documentation on how to use it](https://developer.android.com/guide/components/loaders.html), and use it correctly, with `LoaderManager.LoaderCallback`. – CommonsWare Feb 20 '18 at 11:45

0 Answers0