I have 2 Xamarin Forms applications. One of them implements ContentProvider and in the other one I use ContentResolver. On Android version 10 (API 29) Everything works without problems, however on later versions (I tested on 12.1 and 14) - the application in which ContentResolver gives the following error: Java.Lang.IllegalArgumentException: 'Unknown URL content://com.nts.user_screen_provider/products' Here is the provider code:
[ContentProvider(new string[] {AUTHORITIES}, Exported = true)]
public class ProductProvider : ContentProvider
{
public const string NAME = "ProductProvider";
public const string PRODUCT_PATH = "products";
public const string AUTHORITIES = "com.nts.user_screen_provider";
public static readonly Android.Net.Uri PRODUCTS_URI = Android.Net.Uri.Parse("content://" + AUTHORITIES + "/" + PRODUCT_PATH);
public const int PRODUCTS_URI_ID = 1;
UriMatcher uriMatcher;
public static class ColumnNames
{
public const string Name = "Name";
public const string Price = "Price";
public const string Weight = "Weight";
public const string Barcode = "Barcode";
public const string Type = "Type";
}
public override Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values)
{
System.Diagnostics.Debug.WriteLine("Insert provider");
int uriType = uriMatcher.Match(uri);
int id = 0;
switch (uriType)
{
case PRODUCTS_URI_ID:
id = IndexOf(values);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
Context.ContentResolver.NotifyChange(uri, null);
return Android.Net.Uri.Parse(PRODUCTS_URI + "/" + id.ToString());
}
public int IndexOf(ContentValues values)
{
int result = -1;
string name = (string)values.Get(ColumnNames.Name);
string priceS = (string)values.Get(ColumnNames.Price);
string weightS = (string)values.Get(ColumnNames.Weight);
string barcodeS = (string)values.Get(ColumnNames.Barcode);
string typeS = (string)values.Get(ColumnNames.Type);
double price = 0;
double weight = 0;
long barcode = 0;
if (!double.TryParse(priceS, out price) || !double.TryParse(weightS, out weight) || !long.TryParse(barcodeS, out barcode)) return result;
Product.CountType type = 0;
try
{
type = typeS switch
{
"Counted" => Product.CountType.Counted,
"Weighted" => Product.CountType.Weighted,
_ => throw new NotImplementedException()
};
}
catch { return result; }
result = AppManager.UserPage.AddProductInt(name, price, weight, barcode, type);
return result;
}
//implement other ovveride voids
}
ContentResolver:
public class ProductSender : IProductSender
{
public const string NAME = "ProductProvider";
public const string PRODUCT_PATH = "products";
public const string AUTHORITIES = "com.nts.user_screen_provider";
public static readonly Android.Net.Uri PRODUCTS_URI = Android.Net.Uri.Parse("content://" + AUTHORITIES + "/" + PRODUCT_PATH);
public void Add(Product product)
{
ContentResolver resolver = Android.App.Application.Context.ContentResolver;
ContentValues values = new ContentValues();
values.Put("Name", product.Name);
values.Put("Price", product.Price.ToString());
values.Put("Weight", product.Weight.ToString());
values.Put("Barcode", product.Barcode.ToString());
values.Put("Type", product.Type.ToString());
Android.Net.Uri uri = resolver.Insert(PRODUCTS_URI, values);
}
}
First app AndroidManifest:
<application android:label="UserScreen.Android" android:theme="@style/MainTheme" android:icon="@mipmap/icon">
<service android:name=".user_screen_service" />
<provider
android:name="com.nts.user_screen.ProductProvider"
android:authorities="com.nts.user_screen_provider"
android:enabled="true"
android:exported="true"
android:grantUriPermissions="true"
android:readPermission="android.permission.BIND_DIRECTORY_SEARCH"
android:writePermission="true"
/>
</application>
Seckond:
<application android:label="TestProductDataBase.Android" android:theme="@style/MainTheme" android:icon="@mipmap/icon"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
I've tried adding and changing permissions in AndroidManifest - no luck, tested on other devices (Android 10 - works, Android 14 - doesn't work).
I replaced the namespace of the class implementing the ContentProvider with this
namespace com.nts.user_screen
{
[ContentProvider(new string[] {AUTHORITIES}, Exported = true)]
public class ProductProvider : ContentProvider
{
//...