allow images to be opened with gallary app

Daniel Gultsch created

Change summary

AndroidManifest.xml                                         |  5 
res/layout/message_recieved.xml                             | 10 
res/values/strings.xml                                      |  3 
src/eu/siacs/conversations/persistance/DatabaseBackend.java | 34 ++
src/eu/siacs/conversations/persistance/FileBackend.java     |  3 
src/eu/siacs/conversations/services/ImageProvider.java      | 97 +++++++
src/eu/siacs/conversations/ui/ConversationFragment.java     | 14 
7 files changed, 161 insertions(+), 5 deletions(-)

Detailed changes

AndroidManifest.xml 🔗

@@ -23,6 +23,11 @@
         android:theme="@android:style/Theme.Holo.Light" >
         <service android:name="eu.siacs.conversations.services.XmppConnectionService" />
 
+         <provider
+             android:name="eu.siacs.conversations.services.ImageProvider"
+             android:authorities="eu.siacs.conversations.images"
+             android:exported="true"/>
+        
         <receiver android:name="eu.siacs.conversations.services.EventReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />

res/layout/message_recieved.xml 🔗

@@ -38,7 +38,15 @@
                 android:autoLink="web"
                 android:textIsSelectable="true"
                 android:textColor="#333333"
-                android:textSize="16sp" />
+                android:textSize="16sp"/>
+
+            <Button
+                android:id="@+id/download_button"
+                style="?android:attr/buttonStyleSmall"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/download_image"
+                android:visibility="gone"/>
 
            <LinearLayout
                 android:layout_width="wrap_content"

res/values/strings.xml 🔗

@@ -55,7 +55,7 @@
     <string name="receiving_image">Receiving image file. Please wait&#8230;</string>
     <string name="preparing_image">Preparing image for transmission. Please wait&#8230;</string>
     <string name="action_clear_history">Clear history</string>
-    <string name="clear_conversation_history">Clear Conversation history</string>
+    <string name="clear_conversation_history">Clear Conversation History</string>
     <string name="clear_histor_msg">Do you want to delete all messages within this Conversation?\n\n<b>Warning:</b> This will not influence messages stored on other devices or servers.</string>
     <string name="delete_messages">Delete messages</string>
     <string name="also_end_conversation">End this conversations afterwards</string>
@@ -65,4 +65,5 @@
     <string name="send_otr_message">Send OTR encrypted message</string>
     <string name="send_pgp_message">Send openPGP encrypted message</string>
     <string name="your_nick_has_been_changed">Your nickname has been changed</string>
+    <string name="download_image">Download Image</string>
 </resources>

src/eu/siacs/conversations/persistance/DatabaseBackend.java 🔗

@@ -305,11 +305,43 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 		SQLiteDatabase db = this.getWritableDatabase();
 		String[] args = { uuid };
 		Cursor cursor = db.query(Contact.TABLENAME, null, Contact.UUID + "=?", args, null, null, null);
-		if (cursor.getCount() == 0)
+		if (cursor.getCount() == 0) {
 			return null;
+		}
 		cursor.moveToFirst();
 		return Contact.fromCursor(cursor);
 	}
 
+	public Conversation findConversationByUuid(String conversationUuid) {
+		SQLiteDatabase db = this.getReadableDatabase();
+		String[] selectionArgs = { conversationUuid };
+		Cursor cursor = db.query(Conversation.TABLENAME, null, Conversation.UUID + "=?", selectionArgs, null, null, null);
+		if (cursor.getCount() == 0) {
+			return null;
+		}
+		cursor.moveToFirst();
+		return Conversation.fromCursor(cursor);
+	}
+
+	public Message findMessageByUuid(String messageUuid) {
+		SQLiteDatabase db = this.getReadableDatabase();
+		String[] selectionArgs = { messageUuid };
+		Cursor cursor = db.query(Message.TABLENAME, null, Message.UUID + "=?", selectionArgs, null, null, null);
+		if (cursor.getCount() == 0) {
+			return null;
+		}
+		cursor.moveToFirst();
+		return Message.fromCursor(cursor);
+	}
 	
+	public Account findAccountByUuid(String accountUuid) {
+		SQLiteDatabase db = this.getReadableDatabase();
+		String[] selectionArgs = { accountUuid };
+		Cursor cursor = db.query(Account.TABLENAME, null, Account.UUID + "=?", selectionArgs, null, null, null);
+		if (cursor.getCount() == 0) {
+			return null;
+		}
+		cursor.moveToFirst();
+		return Account.fromCursor(cursor);
+	}
 }

src/eu/siacs/conversations/persistance/FileBackend.java 🔗

@@ -14,8 +14,10 @@ import android.net.Uri;
 import android.util.Log;
 import android.util.LruCache;
 
+import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.services.XmppConnectionService;
 import eu.siacs.conversations.xmpp.jingle.JingleFile;
 
 public class FileBackend {
@@ -27,7 +29,6 @@ public class FileBackend {
 
 	public FileBackend(Context context) {
 		this.context = context;
-
 		int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
 		int cacheSize = maxMemory / 8;
 		thumbnailCache = new LruCache<String, Bitmap>(cacheSize) {

src/eu/siacs/conversations/services/ImageProvider.java 🔗

@@ -0,0 +1,97 @@
+package eu.siacs.conversations.services;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.persistance.DatabaseBackend;
+import eu.siacs.conversations.persistance.FileBackend;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+public class ImageProvider extends ContentProvider {
+
+	@Override
+	public ParcelFileDescriptor openFile(Uri uri, String mode)
+			throws FileNotFoundException {
+		DatabaseBackend databaseBackend = DatabaseBackend
+				.getInstance(getContext());
+		FileBackend fileBackend = new FileBackend(getContext());
+		String uuids = uri.getPath();
+		Log.d("xmppService", "uuids = " + uuids);
+		if (uuids == null) {
+			throw new FileNotFoundException();
+		}
+		String[] uuidsSplited = uuids.split("/");
+		if (uuidsSplited.length != 3) {
+			throw new FileNotFoundException();
+		}
+		String conversationUuid = uuidsSplited[1];
+		String messageUuid = uuidsSplited[2];
+
+		Conversation conversation = databaseBackend
+				.findConversationByUuid(conversationUuid);
+		if (conversation == null) {
+			throw new FileNotFoundException("conversation " + conversationUuid
+					+ " could not be found");
+		}
+		Message message = databaseBackend.findMessageByUuid(messageUuid);
+		if (message == null) {
+			throw new FileNotFoundException("message " + messageUuid
+					+ " could not be found");
+		}
+
+		Account account = databaseBackend.findAccountByUuid(conversation
+				.getAccountUuid());
+		if (account == null) {
+			throw new FileNotFoundException("account "
+					+ conversation.getAccountUuid() + " cound not be found");
+		}
+		message.setConversation(conversation);
+		conversation.setAccount(account);
+
+		File file = fileBackend.getJingleFile(message);
+		ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file,
+				ParcelFileDescriptor.MODE_READ_ONLY);
+		return pfd;
+	}
+
+	@Override
+	public int delete(Uri arg0, String arg1, String[] arg2) {
+		return 0;
+	}
+
+	@Override
+	public String getType(Uri arg0) {
+		return null;
+	}
+
+	@Override
+	public Uri insert(Uri arg0, ContentValues arg1) {
+		return null;
+	}
+
+	@Override
+	public boolean onCreate() {
+		return false;
+	}
+
+	@Override
+	public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
+			String arg4) {
+		return null;
+	}
+
+	@Override
+	public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
+		return 0;
+	}
+
+}

src/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -31,6 +31,7 @@ import android.content.SharedPreferences;
 import android.content.IntentSender.SendIntentException;
 import android.graphics.Bitmap;
 import android.graphics.Typeface;
+import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
@@ -197,7 +198,7 @@ public class ConversationFragment extends Fragment {
 
 			@Override
 			public View getView(int position, View view, ViewGroup parent) {
-				Message item = getItem(position);
+				final Message item = getItem(position);
 				int type = getItemViewType(position);
 				ViewHolder viewHolder;
 				if (view == null) {
@@ -283,6 +284,17 @@ public class ConversationFragment extends Fragment {
 							viewHolder.image.setImageBitmap(thumbnail);
 							viewHolder.messageBody.setVisibility(View.GONE);
 							viewHolder.image.setVisibility(View.VISIBLE);
+							viewHolder.image.setOnClickListener(new OnClickListener() {
+								
+								@Override
+								public void onClick(View v) {
+									Uri uri = Uri.parse("content://eu.siacs.conversations.images/"+item.getConversationUuid()+"/"+item.getUuid());
+									Log.d("xmppService","staring intent with uri:"+uri.toString());
+									Intent intent = new Intent(Intent.ACTION_VIEW);
+								    intent.setDataAndType(uri, "image/*");
+								    startActivity(intent);
+								}
+							});
 						} catch (FileNotFoundException e) {
 							viewHolder.image.setVisibility(View.GONE);
 							viewHolder.messageBody.setText("error loading image file");