didi/DoKit · warning · FileNotFoundException

Unable to obtain resources for package: " + data.uri

Error message

Unable to obtain resources for package: " + data.uri

What it means

Utils.getResources(Context, Request) maps the URI's authority (package name) to a Resources instance via PackageManager.getResourcesForApplication(pkg). If that package is not installed, NameNotFoundException is caught and rethrown as FileNotFoundException('Unable to obtain resources for package: <uri>'). This is the standard failure when loading a resource URI that points at another app's package which is not available.

Source

Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/Utils.java:372

      id = resources.getIdentifier(name, type, pkg);
    } else {
      throw new FileNotFoundException("More than two path segments: " + data.uri);
    }
    return id;
  }

  static Resources getResources(Context context, Request data) throws FileNotFoundException {
    if (data.resourceId != 0 || data.uri == null) {
      return context.getResources();
    }

    String pkg = data.uri.getAuthority();
    if (pkg == null) throw new FileNotFoundException("No package provided: " + data.uri);
    try {
      PackageManager pm = context.getPackageManager();
      return pm.getResourcesForApplication(pkg);
    } catch (PackageManager.NameNotFoundException e) {
      throw new FileNotFoundException("Unable to obtain resources for package: " + data.uri);
    }
  }

  /**
   * Prior to Android 5, HandlerThread always keeps a stack local reference to the last message
   * that was sent to it. This method makes sure that stack local reference never stays there
   * for too long by sending new messages to it every second.
   */
  static void flushStackLocalLeaks(Looper looper) {
    Handler handler = new Handler(looper) {
      @Override public void handleMessage(Message msg) {
        sendMessageDelayed(obtainMessage(), THREAD_LEAK_CLEANING_MS);
      }
    };
    handler.sendMessageDelayed(handler.obtainMessage(), THREAD_LEAK_CLEANING_MS);
  }

  @TargetApi(HONEYCOMB)

View on GitHub (pinned to 626827cddb)

Solutions

  1. Check installation first: context.getPackageManager().getPackageInfo(pkg, 0) in try/catch, or getApplicationInfo(pkg, 0), before issuing the load.
  2. Fall back to a bundled resource when the target package is missing.
  3. Use getPackageManager().canResolvePackage / queryIntentActivities to gate optional-app resource loads at a higher level.

Example fix

// before
picasso.load(Uri.parse("android.resource://com.other.app/drawable/icon")).into(iv);

// after
String pkg = "com.other.app";
try {
    context.getPackageManager().getPackageInfo(pkg, 0);
    picasso.load(Uri.parse("android.resource://" + pkg + "/drawable/icon")).into(iv);
} catch (PackageManager.NameNotFoundException e) {
    iv.setImageResource(R.drawable.default_icon);
}
Defensive patterns

Strategy: try-catch

Validate before calling

static boolean pkgInstalled(Context ctx, String pkg) {
    try {
        ctx.getPackageManager().getPackageInfo(pkg, 0);
        return true;
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

Try / catch

// Not surfaced as NameNotFoundException; Picasso wraps it. Guard before the load:
if (pkgInstalled(context, pkg)) {
    picasso.load(resourceUri).into(iv);
} else {
    iv.setImageResource(R.drawable.fallback);
}

Prevention

When it happens

Trigger: Passing android.resource://com.other.app/drawable/foo where com.other.app is not installed on the device; package renamed so the authority no longer matches any installed package; querying a package while it is being uninstalled/updated.

Common situations: Loading plugin/other-app resources (e.g. themes or icon packs) without checking installation; hard-coded package names that change across app versions; emulator vs. device differences where an optional companion app is absent.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/3f4f19c50fd484d0. Report an issue: GitHub.