mirror of
				https://github.com/pierre42100/ComunicAndroid
				synced 2025-10-31 09:34:47 +00:00 
			
		
		
		
	Can save some uploaded images
This commit is contained in:
		| @@ -13,6 +13,10 @@ | ||||
|     <uses-permission android:name="android.permission.RECORD_AUDIO" /> | ||||
|  | ||||
|  | ||||
|     <!-- To save file (eg. images) into user storage --> | ||||
|     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | ||||
|  | ||||
|  | ||||
|     <application | ||||
|         android:allowBackup="true" | ||||
|         android:fullBackupContent="@xml/backup_scheme" | ||||
|   | ||||
| @@ -7,6 +7,8 @@ import android.widget.ImageView; | ||||
|  | ||||
| import org.communiquons.android.comunic.client.data.runnables.ImageLoadRunnable; | ||||
|  | ||||
| import java.util.Objects; | ||||
|  | ||||
| /** | ||||
|  * Image load manager / helper | ||||
|  * | ||||
| @@ -95,6 +97,20 @@ public class ImageLoadHelper { | ||||
|         clean(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check out whether an image view is loading or not | ||||
|      * | ||||
|      * @param v The target view | ||||
|      * @return TRUE if loading / FALSE else | ||||
|      */ | ||||
|     public static boolean IsLoading(View v){ | ||||
|  | ||||
|         return threads.containsKey(v) | ||||
|                 && threads.get(v) != null | ||||
|                 && Objects.requireNonNull(threads.get(v)).isAlive() | ||||
|                 && !Objects.requireNonNull(threads.get(v)).isInterrupted(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Clean the list of pending operations | ||||
|      */ | ||||
|   | ||||
| @@ -28,12 +28,12 @@ public class ImageLoadRunnable implements Runnable { | ||||
|     /** | ||||
|      * Debug tag | ||||
|      */ | ||||
|     private static final String TAG = "ImageLoadRunnable"; | ||||
|     private static final String TAG = ImageLoadRunnable.class.getSimpleName(); | ||||
|  | ||||
|     /** | ||||
|      * Image load lock | ||||
|      */ | ||||
|     public static ReentrantLock ImageLoadLock = null; | ||||
|     private static ReentrantLock ImageLoadLock = null; | ||||
|  | ||||
|     /** | ||||
|      * An array map with all the pending images associated with their URLs | ||||
| @@ -89,11 +89,7 @@ public class ImageLoadRunnable implements Runnable { | ||||
|         //Create the parent directory if required | ||||
|         ImageLoadUtils.create_parent_directory(mContext); | ||||
|  | ||||
|         //Determine the filename for the requested URL | ||||
|         String filename = ImageLoadUtils.IMAGE_CACHE_DIRECTORY + ImageLoadUtils.get_file_name(url); | ||||
|  | ||||
|         //Create file object | ||||
|         file = new File(mContext.getCacheDir(), filename); | ||||
|         file = ImageLoadUtils.getFileForImage(mContext, url); | ||||
|  | ||||
|         //Check no thread is already running for the following image | ||||
|         if (!pendingOperation.containsKey(url)) { | ||||
| @@ -181,7 +177,8 @@ public class ImageLoadRunnable implements Runnable { | ||||
|                         " deleted"); | ||||
|  | ||||
|                 //Delete file | ||||
|                 file.delete(); | ||||
|                 if(!file.delete()) | ||||
|                     Log.e(TAG, "Could not delete file " + file.getPath() + " !"); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|   | ||||
| @@ -22,7 +22,7 @@ public class ImageLoadUtils { | ||||
|     /** | ||||
|      * The main folder in the cache directory that stores the file | ||||
|      */ | ||||
|     public static final String IMAGE_CACHE_DIRECTORY = "img_cache/"; | ||||
|     private static final String IMAGE_CACHE_DIRECTORY = "img_cache/"; | ||||
|  | ||||
|     /** | ||||
|      * Get the file name, based on the URL name | ||||
| @@ -30,10 +30,28 @@ public class ImageLoadUtils { | ||||
|      * @param url The URL of the file | ||||
|      * @return The name of the file, composed of characters that can be used in filename | ||||
|      */ | ||||
|     public static String get_file_name(String url){ | ||||
|     private static String get_file_name(String url){ | ||||
|         return StringsUtils.sha1(url); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the File object corresponding to an image URL | ||||
|      * | ||||
|      * Warning ! In some cases, the file might not exists | ||||
|      * | ||||
|      * @param context Application context | ||||
|      * @param url URL of the target image | ||||
|      * @return File object pointing on the image | ||||
|      */ | ||||
|     public static File getFileForImage(Context context, String url){ | ||||
|  | ||||
|         //Determine the filename for the requested URL | ||||
|         String filename = IMAGE_CACHE_DIRECTORY + ImageLoadUtils.get_file_name(url); | ||||
|  | ||||
|         //Create file object | ||||
|         return new File(context.getCacheDir(), filename); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create cache images files parent directory if it does not exist | ||||
|      * | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package org.communiquons.android.comunic.client.ui.activities; | ||||
|  | ||||
| import android.Manifest; | ||||
| import android.app.Activity; | ||||
| import android.app.AlertDialog; | ||||
| import android.app.Dialog; | ||||
| @@ -25,6 +26,7 @@ import android.widget.Toast; | ||||
|  | ||||
| import org.communiquons.android.comunic.client.BuildConfig; | ||||
| import org.communiquons.android.comunic.client.R; | ||||
| import org.communiquons.android.comunic.client.ui.utils.PermissionsUtils; | ||||
| import org.communiquons.crashreporter.CrashReporter; | ||||
| import org.communiquons.android.comunic.client.data.enums.VirtualDirectoryType; | ||||
| import org.communiquons.android.comunic.client.data.helpers.APIRequestHelper; | ||||
| @@ -193,6 +195,11 @@ public class MainActivity extends BaseActivity implements | ||||
|         GetCallConfigurationTask callConfigurationTask = new GetCallConfigurationTask(this); | ||||
|         callConfigurationTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||
|         getTasksManager().addTask(callConfigurationTask); | ||||
|  | ||||
|         //Request a few permissions | ||||
|         PermissionsUtils.RequestPermissions(this, | ||||
|                 new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -91,6 +91,7 @@ class CommentsAdapter extends ArrayAdapter<Comment> { | ||||
|  | ||||
|         //Update comment image (if any) | ||||
|         EnlargeableWebImageView commentImage = view.findViewById(R.id.comment_image); | ||||
|         commentImage.setCanSaveImageToGallery(true); | ||||
|         if(comment.getImage_url().length() < 5) | ||||
|             commentImage.setVisibility(View.GONE); | ||||
|         else { | ||||
|   | ||||
| @@ -136,6 +136,7 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter { | ||||
|  | ||||
|             mMessage.setOnLongClickListener(this); | ||||
|             mImage.setOnLongClickListener(this); | ||||
|             mImage.setCanSaveImageToGallery(true); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|   | ||||
| @@ -415,6 +415,7 @@ public class PostsAdapter extends BaseRecyclerViewAdapter { | ||||
|             super(itemView); | ||||
|  | ||||
|             mPostImage = new EnlargeableWebImageView(getContext()); | ||||
|             mPostImage.setCanSaveImageToGallery(true); | ||||
|             getAdditionalViewsLayout().addView(mPostImage, | ||||
|                     new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, | ||||
|                             UiUtils.GetPixel(getContext(), 200))); | ||||
|   | ||||
| @@ -0,0 +1,44 @@ | ||||
| package org.communiquons.android.comunic.client.ui.utils; | ||||
|  | ||||
| import android.app.Activity; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.v4.app.ActivityCompat; | ||||
| import android.support.v4.content.ContextCompat; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
|  | ||||
| /** | ||||
|  * Permissions utilities | ||||
|  * | ||||
|  * @author Pierre HUBERT | ||||
|  */ | ||||
| public class PermissionsUtils { | ||||
|  | ||||
|     /** | ||||
|      * Request some permissions from the user | ||||
|      * | ||||
|      * @param activity Activity that perform the request | ||||
|      * @param permissions Requested permissions | ||||
|      */ | ||||
|     public static void RequestPermissions(@NonNull Activity activity, String[] permissions, int c){ | ||||
|  | ||||
|         ArrayList<String> permissionsToRequest = new ArrayList<>(); | ||||
|  | ||||
|         for(String permission : permissions){ | ||||
|             if(ContextCompat.checkSelfPermission(activity, permission) | ||||
|                     != PackageManager.PERMISSION_GRANTED) | ||||
|                 permissionsToRequest.add(permission); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         //Ask for permissions if required | ||||
|         if(permissionsToRequest.size() > 0){ | ||||
|             String[] permissionsArray = permissionsToRequest.toArray(new String[0]); | ||||
|             assert permissionsArray != null; | ||||
|             ActivityCompat.requestPermissions(activity, permissionsArray, c); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -2,11 +2,22 @@ package org.communiquons.android.comunic.client.ui.views; | ||||
|  | ||||
| import android.app.AlertDialog; | ||||
| import android.content.Context; | ||||
| import android.graphics.Bitmap; | ||||
| import android.provider.MediaStore; | ||||
| import android.util.AttributeSet; | ||||
| import android.util.Log; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.MenuItem; | ||||
| import android.view.View; | ||||
| import android.widget.PopupMenu; | ||||
| import android.widget.Toast; | ||||
|  | ||||
| import org.communiquons.android.comunic.client.R; | ||||
| import org.communiquons.android.comunic.client.data.helpers.ImageLoadHelper; | ||||
| import org.communiquons.android.comunic.client.data.utils.ImageLoadUtils; | ||||
| import org.communiquons.android.comunic.client.ui.utils.BitmapUtils; | ||||
|  | ||||
| import java.io.File; | ||||
|  | ||||
| /** | ||||
|  * Enlargeable images view. | ||||
| @@ -17,13 +28,21 @@ import org.communiquons.android.comunic.client.R; | ||||
|  * Created by pierre on 4/28/18. | ||||
|  */ | ||||
|  | ||||
| public class EnlargeableWebImageView extends WebImageView { | ||||
| public class EnlargeableWebImageView extends WebImageView implements PopupMenu.OnMenuItemClickListener { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Debug tag | ||||
|      */ | ||||
|     private static final String TAG = EnlargeableWebImageView.class.getSimpleName(); | ||||
|  | ||||
|     /** | ||||
|      * Optional additional OnClick Listener | ||||
|      */ | ||||
|     private OnClickListener mOnClickListener; | ||||
|  | ||||
|     private boolean mCanSaveImageToGallery; | ||||
|  | ||||
|     public EnlargeableWebImageView(Context context) { | ||||
|         super(context); | ||||
|         init(); | ||||
| @@ -68,6 +87,14 @@ public class EnlargeableWebImageView extends WebImageView { | ||||
|         return mOnClickListener == null; | ||||
|     } | ||||
|  | ||||
|     public boolean isCanSaveImageToGallery() { | ||||
|         return mCanSaveImageToGallery; | ||||
|     } | ||||
|  | ||||
|     public void setCanSaveImageToGallery(boolean mCanSaveImageToGallery) { | ||||
|         this.mCanSaveImageToGallery = mCanSaveImageToGallery; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Open the image in large dimensions | ||||
|      */ | ||||
| @@ -86,5 +113,80 @@ public class EnlargeableWebImageView extends WebImageView { | ||||
|                 .show(); | ||||
|  | ||||
|  | ||||
|         //Offer the user to save if image if possible | ||||
|         if(isCanSaveImageToGallery()){ | ||||
|             image.setOnLongClickListener(this::openContextMenu); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Open context menu for the image | ||||
|      */ | ||||
|     private boolean openContextMenu(View v){ | ||||
|  | ||||
|         //Show popup menu | ||||
|         PopupMenu popupMenu = new PopupMenu(getContext(), v); | ||||
|         popupMenu.inflate(R.menu.image_menu); | ||||
|         popupMenu.setOnMenuItemClickListener(this); | ||||
|  | ||||
|         if(ImageLoadHelper.IsLoading(this)) | ||||
|             popupMenu.getMenu().findItem(R.id.action_save_image_in_gallery).setEnabled(false); | ||||
|  | ||||
|  | ||||
|         popupMenu.show(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean onMenuItemClick(MenuItem item) { | ||||
|  | ||||
|  | ||||
|         if(item.getItemId() == R.id.action_save_image_in_gallery){ | ||||
|  | ||||
|             if(!saveImageToGallery()) | ||||
|                 Toast.makeText(getContext(), R.string.err_save_image_in_gallery, Toast.LENGTH_SHORT).show(); | ||||
|             else | ||||
|                 Toast.makeText(getContext(), R.string.success_save_image_in_gallery, Toast.LENGTH_SHORT).show(); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Save the current image in this {@link WebImageView} into the gallery | ||||
|      * | ||||
|      * @return TRUE in case of success / FALSE else | ||||
|      */ | ||||
|     private boolean saveImageToGallery(){ | ||||
|  | ||||
|         try { | ||||
|             if (ImageLoadHelper.IsLoading(this)) | ||||
|                 return false; | ||||
|  | ||||
|             File file = ImageLoadUtils.getFileForImage(getContext(), getCurrURL()); | ||||
|  | ||||
|             if (!file.isFile()) { | ||||
|                 Log.e(TAG, "Image is not a file!"); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             Bitmap bm = BitmapUtils.openResized(file, 1500, 1500); | ||||
|  | ||||
|             //Save the image into the gallery | ||||
|             return MediaStore.Images.Media.insertImage( | ||||
|                     getContext().getContentResolver(), | ||||
|                     bm, | ||||
|                     "Comunic image", | ||||
|                     getCurrURL() | ||||
|             ) != null; | ||||
|  | ||||
|         } catch (Exception e){ | ||||
|             e.printStackTrace(); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										10
									
								
								app/src/main/res/menu/image_menu.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app/src/main/res/menu/image_menu.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <menu xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|  | ||||
|     <item | ||||
|         android:id="@+id/action_save_image_in_gallery" | ||||
|         android:title="@string/action_save_image_in_gallery" | ||||
|         /> | ||||
|  | ||||
|  | ||||
| </menu> | ||||
| @@ -335,4 +335,7 @@ | ||||
|     <string name="action_hang_up">Raccrocher</string> | ||||
|     <string name="action_switch_camera">Changer de caméra</string> | ||||
|     <string name="action_stop_camera">Arrêter la caméra</string> | ||||
|     <string name="action_save_image_in_gallery">Enregistrer dans la gallerie</string> | ||||
|     <string name="err_save_image_in_gallery">Une erreur a survenue lors de l\'enregistrement de l\'image dans la gallerie !</string> | ||||
|     <string name="success_save_image_in_gallery">L\'image a bien été enregistrée dans la gallerie !</string> | ||||
| </resources> | ||||
| @@ -334,4 +334,7 @@ | ||||
|     <string name="action_hang_up">Hang up</string> | ||||
|     <string name="action_switch_camera">Switch camera</string> | ||||
|     <string name="action_stop_camera">Stop camera</string> | ||||
|     <string name="action_save_image_in_gallery">Save in gallery</string> | ||||
|     <string name="err_save_image_in_gallery">Could not save the image in the gallery!</string> | ||||
|     <string name="success_save_image_in_gallery">Successfully saved the image into the gallery!</string> | ||||
| </resources> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user