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