Displaying all the images from storage at once in Phimpme Android Application

In the Phimpme Android application, the images are displayed in the albums in which they are indexed in the device’s storage. However, there is also an “All photos” section in the application where all the images present in the device’s storage are displayed at once irrespective of the folder they’re indexed in. So in this post, I will be discussing how we achieved the “All Photos”  functionality.

Android framework provides developers with a media content provider class called MediaStore. It contains metadata for all available media on both internal and external storage devices. With the help of particular methods we can obtain metadata for all the images stored in the device’s storage.

Step 1

So First we need to get the Uri from MediaStore content provider pointing to the media(here media refers to the photos stored on the device). This can be done by the following snippet of code.

Uri uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

Step 2

Now retrieving a cursor object containing the data column for the image media is required to be performed. The data column will contain the path to the particular image files on the disk. This can be done by querying the MediaColumns table of the MediaStore class, which can be performed by the use of the content resolver query method. The mentioned functionality can be achieved by the following lines of code.

String[] projection = {MediaStore.MediaColumns.DATA};
Cursor cursor = activity.getContentResolver().query(uri, projection, null, null, null);

Step 3

In the final step, we would retrieve the path of all the images by iterating through the cursor object obtained in the previous step and keep adding those paths to an ArrayList<String>. Creating Media objects passing in the image path and concurrently adding those Media objects to an ArrayList<Media> to be done thereafter. Finally, the dataset(ArrayList<Media> in this case) containing Media objects for all the images is required to be passed to the Media Adapter in order to display all the photos in the UI. The code snippets used for the final steps are provided below.

while (cursor.moveToNext()) {
  absolutePathOfImage = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));
  listOfAllImages.add(absolutePathOfImage);
}
ArrayList<Media> list = new ArrayList<>();

for (String path : listOfAllImages) {
  list.add(new Media(new File(path)));
}
return list;

This is how we achieved the functionality to display all the images from the storage on a single screen(at once) in the Phimpme Android application. To get the full source code, please refer to the Phimpme Android Github repository listed in the resource section below.

The screenshot for displaying the “All photos” section is provided below.

Resources

1.Android Developer Guide – https://developer.android.com/reference/android/provider/MediaStore

2.Github-Phimpme Android Repository – https://github.com/fossasia/phimpme-android/

3.Displaying all the images from gallery in android – https://deepshikhapuri.wordpress.com/2017/03/20/get-all-images-from-gallery-in-android-programmatically/

Option to secure particular albums in Phimpme Android Application

In the Phimpme Android application, users can perform various operations on the albums available such as creating a zip file of the album, rename an album and many more. However, one another useful functionality that has been added to the Phimpme Android application is the option to secure particular albums. So in this post, I will be discussing the implementation of this security feature.

Step 1

Firstly, a view item for providing the option to enable security for particular albums is required to be added to the security settings layout. The two-state toggle switch widget provided by the Android framework along with a textview has been added as the required view item. A screenshot depicting the layout change is provided below.

The code snippet representing the operation is provided below.

<TextView
  android:id=“@+id/security_body_apply_folders_title”
  android:layout_width=“wrap_content”
  android:layout_height=“wrap_content”
  android:text=“@string/local_folder”
  android:textColor=“@color/md_dark_background”
  android:textSize=“@dimen/medium_text” />

<android.support.v7.widget.SwitchCompat
  android:id=“@+id/security_body_apply_folder_switch”
  android:layout_width=“wrap_content”
  android:layout_height=“wrap_content”
  android:layout_alignParentEnd=“true”
  android:layout_centerVertical=“true”
  android:layout_gravity=“center_vertical”
  android:button=“@null”
  android:hapticFeedbackEnabled=“true” />

Step 2

Now we need to keep track of the albums selected by the user to secure. This can be done by storing the selected album/albums paths in an ArrayList<String> which can be referred later when required in the process.

The required code snippet to perform the above mentioned operation is provided below.

holder.foldercheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b){
securedfol.add(a.getPath());
a.setsecured(true);
}else{
securedfol.remove(a.getPath());
a.setsecured(false);
}
}
});

Step 3

Now we need to store the selected albums preference in the SharedPreference so that the user’s security preference persists even when the user exits the application and the user doesn’t have to redo the securing operation the next time user launches the application. The ArrayList<String> object containing the path of the user choice albums are converted to JSON representation by the use of the Gson Java library and the string key denoting the JSON representation of the list is saved in the SharedPreference thereafter.

if(securedfol.size()>0){
  SharedPreferences.Editor editor = SP.getEditor();
  Gson gson = new Gson();
  String securedfolders = gson.toJson(securedfol);
  editor.putString(getString(R.string.preference_use_password_secured_local_folders), securedfolders);
  editor.commit();}

Now at the time of performing other operations on the secured folders, the list containing the secured folder paths is retrieved from SharedPreference and the choosen folder’s path is searched in the obtained list, then the user is asked to authenticate accordingly.

This is how we have implemented the functionality to secure particular albums in the Phimpme Android application. To get the full source code, please refer to the Phimpme Android Github repository listed in the resource section below.

Resources

1.Android Developer Guide –
https://developer.android.com/training/data-storage/shared-preferences

2.Github-Phimpme Android Repository – https://github.com/fossasia/phimpme-android/

3.Gson Java library tutorial –
http://www.vogella.com/tutorials/JavaLibrary-Gson/article.html

Implementing Search Functionality in Phimpme Android Application.

In the Phimpme Android application, users are provided with options to perform various operations on the albums available such as move, creating a zip file of the album, rename an album and many more. However, one another useful functionality that has been added to the Phimpme Android application is the option to search albums. So in this post, I will be discussing the implementation of search functionality.

Step 1

Android framework provides developers with a search widget called SearchView that provides a user interface for the user to search a query and submit the request. So first setting up the widget in the action bar of the activity is required. The searchview widget can be added to the action bar as a menu item by adding the following lines in the XML menu resource file menu_albums.xml.

<item
  android:id=“@+id/search_action”
  android:title=“@string/search_menu”
  android:visible=“true”
  android:icon=“@drawable/ic_search_black_24dp”
  android:tint=“@color/white”
  app:actionViewClass=“android.support.v7.widget.SearchView”
  app:showAsAction=“always” />

Step 2

Now SearchView.OnQueryTextListener interface is used for initiating the search operation and listening to the callbacks for changes to the query text. For the purpose of listening to the querytext, two methods are used here both of which are listed below.

onQueryTextChanged(String Text) – This method is called every time the query text is changed by the user and returns a boolean value, false if SearchView should perform the default action of showing any suggestions and true if the action was handled by the listener.

onQueryTextSubmit(String query) – This method is called when the user submits a query which could be done with a key press on the keyboard or by pressing the submit button. It also returns a boolean value which is true if the query has been handled by the listener, otherwise false.

The code snippet for the implementation of the above mentioned interface is provided below.

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
  @Override
  public boolean onQueryTextSubmit(String query) {
      return false;
  }

  @Override
  public boolean onQueryTextChange(String newText) {
      return searchTitle(newText);
  }
});

Step 3

In the final step, with the use of the onQueryTextChange method of the SearchView.onQueryTextListener interface the search operation and displaying the search results in the UI can be achieved. The onQueryTextChange method is called every time the search-query text changes. From the onQueryTextChange method, another method named searchTitle is invoked. Inside the searchTitle method the album names matching the search-query are searched from an Arraylist<Albums> containing all the albums displayed in the application. The albums obtained as a result of the search operation are then stored in another Arraylist<Album> which is thereafter passed as a parameter to the swapDataSet method of the AlbumsAdapter class to display the searched albums in the album view. The code snippet used for the above operations is provided below.

public boolean searchTitle(String newText) {
  if (!fromOnClick) {
      String queryText = newText;
      queryText = queryText.toLowerCase();
      final ArrayList<Album> newList = new ArrayList<>();
      for (Album album : albList) {
          String name = album.getName().toLowerCase();
          if (name.contains(queryText)) {
              newList.add(album);
          }
      }
      if(newList.isEmpty()){
          checkNoSearchResults(newText);
      }
      else{
          if(textView.getVisibility() == View.VISIBLE){
              textView.setVisibility(View.INVISIBLE);
          }
      }
      albumsAdapter.swapDataSet(newList);
  } else {
      fromOnClick = false;
  }
  return true;
}

This is how we have implemented the search functionality in the Phimpme Android application. To get the full source code, please refer to the Phimpme Android Github repository.

The screenshot for displaying the search result in album view is provided below.

Resources

1.Android Developer Guide – https://developer.android.com/reference/android/widget/SearchView

2.Github-Phimpme Android Repository – https://github.com/fossasia/phimpme-android/

3.Creating a search interface in Android – https://medium.com/@yugandhardcs21/creating-a-search-interface-in-android-dc1fd6a53b4

Option to exclude albums in Phimpme Android Application

In the Phimpme Android Application, users can perform various operations on the albums available such as move, creating a .zip file of the album, rename an album, delete the album and much more. However one another important functionality that has been implemented in the application is the option to exclude album/albums. In this post we will be discussing how we achieved the functionality to exclude albums in Phimpme Android Application.

Step 1

First we need to keep track of the albums selected by the user to exclude. This can be done by storing the selected albums in an Arraylist<Album> which can be referred later when required for the process of exclusion. The storing of the albums can be done with the help of following lines of code.

private int toggleSelectAlbum(int index) {
if (dispAlbums.get(index) != null) {
  dispAlbums.get(index).setSelected(!dispAlbums.get(index).isSelected());
  if (dispAlbums.get(index).isSelected()) selectedAlbums.add(dispAlbums.get(index));
  else selectedAlbums.remove(dispAlbums.get(index));
}
return index;
}

Step 2

After the selected albums are stored in an Arraylist<Album>, a function call of excludeSelectedAlbums() of HandlingAlbums class is done passing in Context as the parameter. In the method excludeSelectedAlbums() the selected albums are retrieved from the Arraylist one by one and another method excludeAlbum() is called with the album, context being passed as the parameters. The code snippet performing the above operation is provided below.

public void excludeSelectedAlbums(Context context) {
for (Album selectedAlbum : selectedAlbums)
  excludeAlbum(context, selectedAlbum);
clearSelectedAlbums();
}

Step 3

Thereafter an instance of class CustomsAlbumHelper is created and excludeAlbum() method is called with path of the album passed as parameter, and the selected album is removed from the list containing the currently displayed albums. Code snippets for the above operations are provided below.

private void excludeAlbum(Context context, Album a) {
CustomAlbumsHelper h = CustomAlbumsHelper.getInstance(context);
h.excludeAlbum(a.getPath());
dispAlbums.remove(a);
}

Step 4

Now in the excludeAlbum() method of CustomsAlbumHelper class a writable instance of albums_settings sqlite database is obtained. A check is performed if the current album is present in the albums table or not, if not then a row representing the current album is created. Thereafter the excluded value for the current album in the table is updated to integer 1 denoting that the album is excluded. The code snippet required for the above mentioned operations are provided below.

public void excludeAlbum(String path) {
  SQLiteDatabase db = this.getWritableDatabase();
  checkAndCreateAlbum(db, path);
  ContentValues values = new ContentValues();
  values.put(ALBUM_EXCLUDED, 1);
  db.update(TABLE_ALBUMS, values, ALBUM_PATH+“=?”, new String[]{    path});
  db.close();
}

This is how we have achieved the functionality of excluding albums in the Phimpme Android application. To get the full source code, please refer to the Phimpme Android GitHub repository listed in the resources section below.

The screenshot for the display of the excluded albums is provided below.

Resources

  1. Android Developer Guide –https://developer.android.com/training/data-storage/sqlite.html
  1. Github-Phimpme Android Repository –https://github.com/fossasia/phimpme-android/
  1. Sqlite Operations Tutorial – https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/

Option to hide albums in Phimpme Android Application

In Phimpme Android Application, users can perform various operations on the albums available such as move, creating a .zip file for the album, delete the album, exclude an album, rename an album, pin an album to the top and more. However one another important functionality that has been added in the application is the option to hide  album/albums. So in this post I will be discussing how we achieved the functionality to hide albums in Phimpme Android Application.

Step 1

First we need to get the albums which are selected to be hidden. This can be done by storing the selected items in an Arraylist<Album> which will keep track of the users choice to hide albums. This can be achieved with the following lines of code.

private int toggleSelectAlbum(int index) {
if (dispAlbums.get(index) != null) {
  dispAlbums.get(index).setSelected(!dispAlbums.get(index).isSelected());
  if (dispAlbums.get(index).isSelected()) selectedAlbums.add(dispAlbums.get(index));
  else selectedAlbums.remove(dispAlbums.get(index));
}
return index;
}

Step 2

After storing of the albums to be hidden a function hideSelectedAlbums() is called with Context being passed as the parameter. Now inside this function we retrieve the albums looping through the Arraylist that stores the albums to be hidden and call another function hideAlbum() passing in the album and context as the parameters. The code snippet representing the above operation is given below.

public void hideSelectedAlbums(Context context) {
for (Album selectedAlbum : selectedAlbums)
  hideAlbum(selectedAlbum, context);
clearSelectedAlbums();
}

Step 3.

Now a .nomedia file is added to the directories/albums which are to be hidden and the android Media Scanner System service is triggered thereafter. As a result of the presence of the .nomedia file inside the directory the Media Scanner service won’t scan the particular directory/album thereby the album will not be picked up at the time of displaying the albums. The code snippet to perform the mentioned operation is provided below.

File dirName = new File(path);
File file = new File(dirName, “.nomedia”);
if (!file.exists()) {
try {
  FileOutputStream out = new FileOutputStream(file);
  out.flush();
  out.close();
  scanFile(context, new String[]{ file.getAbsolutePath() });
} catch (Exception e) {
  e.printStackTrace();
}
}

The screenshot for the display of hidden folders is provided below.

This is how we have achieved the functionality of hiding albums in the Phimpme Android application. To get the full source code, please refer to the Phimpme Android GitHub repository listed in the resources section below.

Resources

  1. Android Developer Guide – https://developer.android.com/reference/android/media/MediaScannerConnection.html
  2. Github-Phimpme Android Repository –https://github.com/fossasia/phimpme-android/
  3. Hiding directories using .nomedia file – http://www.easycodeway.com/2016/08/hide-files-in-android-using-nomedia-file.html

Displaying Image location Address In Phimpme Android Application

In Phimpme Android application one of the features available is to view the details of any image. The details consists of attributes including Date and time at which the image was captured, size of the image, title, path, EXIF data, description added to the image, location etc. However in the location attribute the location coordinates of the image as well as the location address can be displayed depending on the user’s preference. The process of obtaining the coordinates from address is called as Geocoding and obtaining string address from coordinates is called reverse Geocoding. So in this post I will be explaining how to implement set of strings denoting the address from the available coordinates.

Step 1

First we need to create an instance of the class Geocoder passing context and function Locale.getDefault() as the parameters.  The function of the attribute Locale.getdefault is provided below.

Locale.getDefault() – It returns the current value of the default locale for the current instance of the Java Virtual Machine. The Java Virtual Machine sets the default locale during startup based on the host environment.The code snippet to perform the above mentioned operation is given below.

Geocoder geocoder = new Geocoder(context, Locale.getDefault());

Step 2

Now a function call of getFromLocation() of the Geocoder class is done where we need to pass the Lattitude and Longitude values of the Location object as parameters. The lattitude and longitudes values can be obtained by the use of the Location object functions getLatitude() and getLongitude() respectively. The function getFromLocation() will return a list of Address objects which will contain the extracted addresses from the passed latitude and longitude values. We also need to pass a third parameter an integer value which will determine the maximum no of addresses to be returned. Here we have requested for a maximum of one address. The following code snippet is used to perform the desired function call.

try {
 List<Address> addressList = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
} catch (IOException e) {
  e.printStackTrace();
}

Step 3

After obtaining the list of Address objects returned from the function call of getFromLocation() we will extract the first address from the list since we want a maximum of 1 address. The Address object will contain information like the address name, country, state, postal code etc. Now the set of strings describing the location can be retrieved with the help of the function getMaxAddressLineIndex() of Address class. The code snippets to perform the above mentioned operations is provided below.

ArrayList<String> addresslines = new ArrayList<String>();
Address address = addressList.get(0);
for(int i = 0; i <= address.getMaxAddressLineIndex(); i++) {
  addresslines.add(address.getAddressLine(i));
}
details.put(context.getString(R.string.location), TextUtils.join(System.getProperty(“line.separator”),
      addresslines));

The screenshot displaying the location address is provided below.

This is how we have achieved the functionality of displaying location address in a set of strings from available coordinates in the Phimpme Android application. To get the full source code, please refer to the Phimpme Android GitHub repository listed in the resources section below.

Resources

1.Android Developer Guide – https://developer.android.com/training/location/display-address.html

2.Github-Phimpme Android Repository – https://github.com/fossasia/phimpme-android/

3.Address Class Guide- https://developer.android.com/reference/android/location/Address.html

 

Leak Canary in Phimpme Android

Leak Canary is a memory detection library for Android and Java. A memory leak occurs when you hold an object for too long after its purpose has been served. If some object is holding another object then the Garbage collector will not be able to collect and this is known as Memory Leak. These memory leaks can be minor (in KB’s) or can lead to an app in ANR state with OutOfMemoryError.Hence to recover and capture this memory leak, Leak Canary is used for Android and Java.

For every functioning done in android, the system needs resource such as memory. Hence in Java the Garbage Collector(GC) plays a major role in deallocating the memory. The GC is mainly used to reclaim memory. Now the question arises, why do we need a memory leak detection library when GC is already present. The answer is sometimes the developers makes programming mistakes and that leads to inhibit the GC to collect the objects that are of no use and mark them as useful objects.

The GC starts from one point(root) and marks active to all the objects that holds references from GC root and the objects which are not marked are wiped out of memory.Hence when some unuseful objects is marked active, memory leak occurs.Hence to eliminate these problems  of memory leaks, we have employed the use of Leak Canary in our project.

The Phimpme project and every related project has possible memory leaks, like for instance we have used fragments in settings activity and to catch that memory leak we have added the refwatcher instance. Hence if any memory leaks occur we get the error such as ‘org.fossasia.phimpme’  leaked 40kb.This can also be checked by Leaks App in the android phone, which has features of showing and sharing the heap dump and info.

To add the Leak Canary in your android app, follow these steps:

  • Add the dependencies in build.gradle(app level)

    dependencies {
       debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
       releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
     }
  • Add the following code to your Application class

    public class MyApplication extends Application{
    @Override
    public void onCreate() {
       if (LeakCanary.isInAnalyzerProcess(this)) {
           // This process is dedicated to LeakCanary for heap analysis.
           // You should not init your app in this process.
           return;
       }
       LeakCanary.install(this);
    }
    
  • Leak canary now will automatically detect the memory leaks  from all activities.

For fragment a refwatcher is needed, hence

public class MYFragment extends Fragment {
    ...

    @Override
    public void onDestroy() {
        super.onDestroy();
        MainApplication.getRefWatcher(getActivity()).watch(this);
    }
}

Hence LeakCanary is setup finally, and now the memory leaks will be detected.

Resources

 

Getting Started Developing on Phimpme Android

Phimpme is an Android app for editing photos and sharing them on social media. To participate in project start by learning how people contribute in open source, learning about the version control system Git and other tools like Codacy and Travis.

Firstly, sign up for GitHub. Secondly, find the open source projects that interest you. Now as for me I started with Phimpme. Then follow these steps:

  1. Go through the project ReadMe.md and read all the technologies and tools they are using.
  2. Now fork that repo in your account.
  3. Open the Android Studio/Other applications that are required for that project and import the project through Git.
  4. For Android Studio sync all the Gradle files and other changes and you are all done and ready for the development process.

Install the app and run it on a phone. Now explore each and every bit use this app as a tester, think about the end cases and boundary condition that will make the app ‘ANR’ (App not responding) dialog appear. Congratulations you are ready to create an issue if that is a verified and original and actually is a bug.

Next,

  • Navigate to the main repo link, you will see an issues section as follows:
  • Create a new issue and report every detail about the issue (logcat, screenshots) For eg. Refer to Issue-1120
  • Now the next step is to work on that issue
  • On your machine, you don’t have to change the code in the development branch as it’s considered to be as a bad practice. Hence checkout as a new branch.
    For eg., I checked out for the above issue as ‘crashfixed’
git checkout -b "Any branch name you want to keep"
  • Make the necessary changes to that branch and test that the code is compiling and the issue is fixed followed by
git add.
git commit -m "Fix #Issue No -Description "
git push origin branch-name
  • Now navigate to the repo and you will an option to create a Pull Request.
    Mention the Issue number and description and changes you done, include screenshots of the fixed app.For eg. Pull Request 1131.

Hence you have done your first contribution in open source while learning with git. The pull request will initiate some checks like Codacy and Travis build and then if everything works it is reviewed and merged by co-developers.

The usual way how this works is, that it should be reviewed by other co-developers. These co-developers do not need merge or write access to the repository. Any developer can review pull requests. This will also help contributors to learn about the project and make the job of core developers easier.

Resources

Showing only Logged-in Accounts in the Sharing Page of Phimpme Android

In Phimpme Android application, users can edit their pictures and share them to a number of platforms ranging from social networking sites like Facebook, Twitter etc to cloud storage and image hosting sites like Box, Dropbox, Imgur etc.

Desired flow of the application

According to the flow of the application, the user has to add an account first i.e. log in to the particular account that needs to be connected to the application. After that when the user enters the share page for sharing the image, a button corresponding to the connected account is visible in that page which on clicking will share the image to that platform directly.

What was happening previously?

The list of accounts which is present in the account manager of Phimpme Android application is also getting displayed in the share image page. As the list is large, it is difficult for the user to find the connected account from the list. There is not even an indicator whether a particular account is connected or not. On clicking the button corresponding to the non-connected account, an error dialog instructing the user to log in from the account manager first, will get displayed.

How we solved it?

We first thought of just adding an indicator on the buttons in the accounts page to show whether it is connected or not. But this fix solves only a single issue. Find the connected account in that large list will be difficult for the user even then. So we decided to remove the whole list and show only the accounts which are connected previously in account manager. This cleans the flow of the accounts and share in  Phimpme Android application

When a user logins from the account manager, the credentials, tokens and other details corresponding to that accounts gets saved in database. We used realm database for saving the details in our application. As the details are present in this database, the list can be dynamically generated when the user opens share image page. We implemented a function in Utils class for getting the list of logged in accounts. Its implementation is shown below.

public static boolean checkAlreadyExist(AccountDatabase.AccountName s) {

   Realm realm = Realm.getDefaultInstance();

   RealmQuery<AccountDatabase> query = realm.where(AccountDatabase.class);

   query.equalTo("name", s.toString());

   RealmResults<AccountDatabase> result1 = query.findAll();

   return (result1.size() > 0);

}



public static ArrayList<AccountDatabase.AccountName> getLoggedInAccountsList(){

   ArrayList<AccountDatabase.AccountName> list = new ArrayList<>();

   for (AccountDatabase.AccountName account : AccountDatabase.AccountName.values()){

       if (checkAlreadyExist(account))

           list.add(account);

   }

   return list;

}

Additional changes

There are few accounts which don’t need authentication. Those accounts need their respective application to be installed in the user’s device. So for adding those accounts to the list, we added another function which checks whether a particular package is installed in user’s device or not. Using that it adds the account to the list. The implementation for checking whether a package is installed or not is shown below.

public static boolean isAppInstalled(String packageName, PackageManager pm) {

   boolean installed;

   try {

       pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);

       installed = true;

   } catch (PackageManager.NameNotFoundException e) {

       installed = false;

   }

   return installed;

}

                 

Resources:

Adding Zooming Functionality For Gallery Images

Phimpme is an Android app which contains the camera, editing, sharing on different platforms and displaying local images. To display local images with swipe feature we also allow the user to zoom images with pinch and double tap action on an image. So in this post, I will be explaining how I added zooming functionality for images in phimpme.

To zoom an image we are using Photoview that is similar to an imageview means it support all option that imageview supports.

Step 1

The first step is to add the following dependency in your Gradle.build file of your project.

dependencies {
   compile 'com.github.chrisbanes:PhotoView:latest.release.here'
}

Step 2

Now replace your imageview with PhotoView and it can be done by following way.

<com.github.chrisbanes.photoview.PhotoView
   android:id="@+id/photo_view"
   android:layout_width="match_parent"
   android:layout_height="match_parent"/>

Now we can use this photoview as imageview and it will enable zoom functionality easily.

Step 3

Now next step is to load image in PhotoView. As phimpme allow to display local images of a device so we are using glide library to load image in PhotoView. We are using URI to load image in Glide.

PhotoView imageView = new PhotoView(ActivitySwitchHelper.context);


Glide.with(getContext())
       .load(media.get(position).getUri())
       .diskCacheStrategy(DiskCacheStrategy.SOURCE)
       .thumbnail(0.5f)
       .into(imageView);

Now your image view which is actually a PhotoView is ready to provide zoom functionality by double tap on and image and by pan-zoom.

PhotoView in Phimpme Android

Resources