Make AvatarProvider implement FileProvider to simplify the implementation
authorDa Risk <da_risk@beem-project.com>
Tue, 27 Oct 2015 01:04:13 +0100
changeset 1069 a2ec39a59c06
parent 1068 5e3cb33d9fe4
child 1070 744a173ea554
Make AvatarProvider implement FileProvider to simplify the implementation
app/src/main/AndroidManifest.xml
app/src/main/java/com/beem/project/beem/providers/AvatarProvider.java
app/src/main/java/com/beem/project/beem/service/BeemAvatarCache.java
app/src/main/res/xml/avatar_paths.xml
--- a/app/src/main/AndroidManifest.xml	Tue Jun 16 09:48:12 2015 +0200
+++ b/app/src/main/AndroidManifest.xml	Tue Oct 27 01:04:13 2015 +0100
@@ -62,8 +62,12 @@
 		-->
 		<provider android:name=".providers.AvatarProvider"
 		    android:authorities="com.beem.project.beem.providers.avatarprovider"
-		    android:exported="true"
-		    />
+		    android:exported="false" android:grantUriPermissions="true" >
+
+		    <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
+			android:resource="@xml/avatar_paths" />
+
+		</provider>
 
 		<service android:name="BeemService" android:enabled="true"
 			android:label="Beem Service" android:permission="com.beem.project.beem.BEEM_SERVICE">
--- a/app/src/main/java/com/beem/project/beem/providers/AvatarProvider.java	Tue Jun 16 09:48:12 2015 +0200
+++ b/app/src/main/java/com/beem/project/beem/providers/AvatarProvider.java	Tue Oct 27 01:04:13 2015 +0100
@@ -44,59 +44,20 @@
 package com.beem.project.beem.providers;
 
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
 
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.UriMatcher;
-import android.database.Cursor;
-import android.database.MatrixCursor;
 import android.net.Uri;
-import android.os.Environment;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
+import android.support.v4.content.FileProvider;
 
 
 /**
  * A simple content provider we expose the differents avatar downloaded.
  *
  */
-public class AvatarProvider extends ContentProvider {
+public class AvatarProvider extends FileProvider {
 
     /** The content uri of this provider. */
     public static final Uri CONTENT_URI =
-        Uri.parse("content://com.beem.project.beem.providers.avatarprovider");
-
-    /** The MIME type of a CONTENT_URI directory of Beem avatars.  */
-    public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.beem.project.beem.avatar";
-
-    /** The MIME type of a CONTENT_URI subdirectory of a single Beem avatar.  */
-    public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.beem.project.beem.avatar";
-
-    /**
-     * Id of the user avatar.
-     */
-    public static final String MY_AVATAR_ID = "my_avatar";
-
-
-    private static final String TAG = AvatarProvider.class.getSimpleName();
-    private static final String AUTHORITY = "com.beem.project.beem.providers.avatarprovider";
-
-    private static String[] columnNames = new String[] {Columns.ID, Columns.DATA};
-
-    private static final int AVATAR = 1;
-    private static final int AVATAR_ID = 2;
-    private static final UriMatcher URIMATCHER = new UriMatcher(AVATAR);
-
-    static
-    {
-        URIMATCHER.addURI(AUTHORITY, "*", AVATAR_ID);
-	// should not be needed if we pass AVATAR on the constructor but it does not work
-        URIMATCHER.addURI(AUTHORITY, null, AVATAR);
-    }
-
-    private String mDataPath;
+	Uri.parse("content://com.beem.project.beem.providers.avatarprovider/avatars/");
 
     /**
      * Create an AvatarProvider.
@@ -106,165 +67,10 @@
 
     @Override
     public boolean onCreate() {
-	File cacheDir = Environment.getExternalStorageDirectory();
-	File dataPath = new File(cacheDir, "/Android/data/com.beem.project.beem/cache/avatar");
-	dataPath.mkdirs();
-	mDataPath = dataPath.getAbsolutePath();
-	return true;
-    }
-
-    @Override
-    public ParcelFileDescriptor openFile(Uri uri, String mode)
-	throws FileNotFoundException {
-    	return openFileHelper(uri, mode);
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
-	MatrixCursor c = new MatrixCursor(columnNames);
-	int match = URIMATCHER.match(uri);
-	switch (match) {
-	    case AVATAR:
-		File[] files = new File(mDataPath).listFiles();
-		if (files != null) {
-		    for (File f : files) {
-			c.newRow().add(f.getName()).add(f.getAbsolutePath());
-		    }
-		}
-		break;
-	    case AVATAR_ID:
-		String id = uri.getPathSegments().get(0);
-		File f = new File(mDataPath, id);
-		if (f.exists() || MY_AVATAR_ID.equals(f.getName()))
-			c.newRow().add(f.getName()).add(f.getAbsolutePath());
-		break;
-	    default:
-		Log.w(TAG, "Unsupported uri for query match = " + match);
-	}
-	if (c != null)
-		c.setNotificationUri(getContext().getContentResolver(), uri);
-	return c;
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-	int match = URIMATCHER.match(uri);
-	String id = null;
-	switch (match) {
-	    case AVATAR_ID:
-		id = uri.getPathSegments().get(0);
-		break;
-	    default:
-		Log.w(TAG, "Unsupported uri for query match = " + match);
-	}
-
-	if (id == null)
-	    return 0;
-
-	File f = new File(mDataPath, id);
-	try {
-	    f.createNewFile();
-	    getContext().getContentResolver().notifyChange(uri, null);
-	    return 1;
-	} catch (IOException e) {
-	    Log.e(TAG, "Error while creating file", e);
-	}
-	return 0;
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-	int res = 0;
-	boolean all = false;
-	String id = null;
-	int match = URIMATCHER.match(uri);
-	switch (match) {
-	    case AVATAR_ID:
-		id = uri.getPathSegments().get(0);
-		break;
-	    case AVATAR:
-		all = true;
-		break;
-	    default:
-		Log.w(TAG, "Unsupported uri for query match = " + match);
-	}
-	File[] list = null;
-	if (id != null) {
-	    list = new File[] {new File(mDataPath, id) };
-	} else if (all) {
-	    list = new File(mDataPath).listFiles();
-	}
-
-	if (list == null)
-	    return res;
-	for (File data : list) {
-	    if (data.exists() && data.delete())
-		res++;
-	}
-	if (res > 0)
-	    getContext().getContentResolver().notifyChange(uri, null);
-	return res;
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-	int match = URIMATCHER.match(uri);
-	String id = null;
-	Uri result = null;
-	switch (match) {
-	    case AVATAR:
-		id = values.getAsString(Columns.ID);
-		result = Uri.withAppendedPath(uri, id);
-		break;
-	    case AVATAR_ID:
-		id = uri.getPathSegments().get(0);
-		result = uri;
-		break;
-	    default:
-		Log.w(TAG, "Unsupported uri for query match = " + match);
-	}
-	if (id == null)
-	    return null;
-
-	File f = new File(mDataPath, id);
-	try {
-	    f.createNewFile();
-	    if (result != null)
-		getContext().getContentResolver().notifyChange(result, null);
-	    return result;
-	} catch (IOException e) {
-	    Log.e(TAG, "Error while creating file", e);
-	}
-	return null;
-    }
-
-    @Override
-    public String getType(Uri uri) {
-    	int match = URIMATCHER.match(uri);
-    	switch (match) {
-    	    case AVATAR:
-    		return CONTENT_TYPE;
-    	    case AVATAR_ID:
-    		return CONTENT_ITEM_TYPE;
-    	    default:
-    		Log.w(TAG, "Unsupported uri for query match = " + match);
-    	}
-	return null;
-    }
-
-    /**
-     * The differents columns available in the AvatarProvider.
-     */
-    public interface Columns {
-
-	/** The id of the avatar.
-	 * type: string */
-	String ID = "_id";
-
-	/** The path of the avatar file.
-	 * type: string
-	 * This field is readonly */
-	String DATA = "_data";
+	File cacheDir = getContext().getCacheDir();
+	File users = new File(cacheDir, "avatar/users");
+	users.mkdirs();
+	return super.onCreate();
     }
 
 }
--- a/app/src/main/java/com/beem/project/beem/service/BeemAvatarCache.java	Tue Jun 16 09:48:12 2015 +0200
+++ b/app/src/main/java/com/beem/project/beem/service/BeemAvatarCache.java	Tue Oct 27 01:04:13 2015 +0100
@@ -56,6 +56,7 @@
 import android.database.Cursor;
 
 import android.net.Uri;
+import android.provider.OpenableColumns;
 
 import com.beem.project.beem.providers.AvatarProvider;
 import com.beem.project.beem.smack.avatar.AvatarCache;
@@ -85,7 +86,6 @@
     @Override
     public void put(String key, byte[] data) throws IOException {
 	Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(key).build();
-	mContentResolver.insert(uri, null);
 	OutputStream os = new BufferedOutputStream(mContentResolver.openOutputStream(uri));
 	try {
 	    os.write(data);
@@ -97,7 +97,6 @@
     @Override
     public void put(String key, InputStream in) throws IOException {
 	Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(key).build();
-	mContentResolver.insert(uri, null);
 	OutputStream os = new BufferedOutputStream(mContentResolver.openOutputStream(uri));
 	try {
 	    byte[] data = new byte[1024];
@@ -129,7 +128,12 @@
     public boolean contains(String key) {
 	Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(key).build();
 	Cursor c = mContentResolver.query(uri, null, null, null, null);
-	boolean res = c.getCount() > 0;
+	boolean res = false;
+	if (c.moveToNext()) {
+	    int sizeIdx = c.getColumnIndex(OpenableColumns.SIZE);
+	    long size = c.getLong(sizeIdx);
+	    res = size > 0;
+	}
 	c.close();
 	return res;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/src/main/res/xml/avatar_paths.xml	Tue Oct 27 01:04:13 2015 +0100
@@ -0,0 +1,3 @@
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+    <cache-path name="avatars" path="avatar/users"/>
+</paths>