How to Make Phimpme Android App Crash Free

Now Phimpme Android app is almost ready with lots of social sharing options. A user can upload images on multiple platforms like Tumblr, Flickr, Imgur, OwnCloud (open source), Nextcloud, dropbox, pinterest, etc. Apart from Sharing, Phimpme app also allow user to click image from own custom camera with different filters and various editing options. As everything is now almost ready so It also important to make app stable and crash free. To make app stable to compatible with all types of device, we can write instrumentation test cases. So in this post I will be explaining how I made Phimpme android app crash free. To do so I have integrated crash reporting service in Phimpme using Firebase Crash report service and Crashlytics. Using Firebase Crash Reporting service: Firebase is free of cost and provide various features along with crash reporting. To integrate firebase crash service there is step by step guide. Step 1: First, step is to register your app on firebase developer console. To register your Android app on firebase click here.  Add your app name and select your country.   Step 2: Next, click on the Add Firebase to your Android app button and fill in the your Android application’s package name and the SHA-1 key. You can generate this key very easily with the help of Android studio. Type this command in your terminal to generate SHA-1 keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android On successful completion of the command, the SHA-1 key will be displayed on the terminal. Step 3: Now add the SHA-1 and package name in firebase console. After that download googleservice.json file and place in app folder of your project. Step 4: Add following dependency in your android project and plugin in build.gradle dependencies {    classpath 'com.google.gms:google-services:3.1.0'  } apply plugin: 'com.google.gms.google-services' Step 5: Once you have done the above four steps your app will be visible in firebase console and now you can add crash service. Now you can see crash in your firebase console After this add the following dependency in build.gradle. This is very important. compile 'com.google.firebase:firebase-crash:9.4.0' Resources: Official firebase documentation: https://firebase.google.com/docs/crash/ Another blog: http://www.androidauthority.com/firebase-crash-reporting-764296/

Continue ReadingHow to Make Phimpme Android App Crash Free

Enhancing Images using Native functions in Phimpme Android

Enhancing the image can be performed by adjusting the brightness, contrast, saturation etc. of that image. In the Phimpme Android Image Application, we implemented many enhancement operations. All these image enhancement operations are performed by the native image processing functions. An image is made up of color channels. A gray-scale image has a single channel, colored opaque image has three channels and colored image with transparency has four channels. Each color channel of an image represents a two dimensional matrix of integer values. An image of resolution 1920x1080 has 1920 elements in its row and 1080 such rows. The integer values present in the matrices will be ranging from 0 to 255. For a grayscale image there will be a single channel. So, for that image, 0 corresponds to black color and 255 corresponds to white color. By changing the value present in the matrices, the image can be modified. The implementation of the enhancement functions in Phimpme Application are given below. Brightness Brightness adjustment is the easiest of the image processing functions in Phimpme. Brightness can be adjusted by increasing or decreasing the values of all elements in all color channel matrices. Its implementation is given below. void tuneBrightness(Bitmap* bitmap, int val) {  register unsigned int i;  unsigned int length = (*bitmap).width * (*bitmap).height;  unsigned char* red = (*bitmap).red;  unsigned char* green = (*bitmap).green;  unsigned char* blue = (*bitmap).blue;  signed char bright = (signed char)(((float)(val-50)/100)*127);  for (i = length; i--; ) {       red[i] =  truncate(red[i]+bright);       green[i] = truncate(green[i]+bright);       blue[i] = truncate(blue[i]+bright);  } }    low brightness, normal, high brightness(in the order) images are shown above For the above function, the argument val is given by the seekbar implemented in java activity. Its value ranges from 0 - 100, so a new variable is introduced to change the range of the input argument in the function. You can see that in the for loop there is function named truncate. As the name suggests it truncates the input argument’s value to accepted range. It is added to the top of the c file as below #define truncate(x) ((x > 255) ? 255 : (x < 0) ? 0 : x) Contrast Contrast of an image is adjusted in Phimpme application by increasing the brightness of the brighter pixel and decreasing value of the darker pixel. This is achieved by using the following formula for the adjustment contrast in editor of phimpme application. pixel[i] = {(259 x (C + 255))/(255 x (259 - C))} x (pixel[i] - 128) In the above formula, C is the contrast value and pixel[i] is the value of the element in the image matrix that we are modifying for changing the contrast.   low contrast, normal, high contrast(in the order) images are shown above So, after this formula for modifying every pixel value, the function looks like below void tuneContrast(Bitmap* bitmap, int val) {  register unsigned int i;  unsigned int length = (*bitmap).width * (*bitmap).height;  unsigned char* red = (*bitmap).red;  unsigned char* green = (*bitmap).green;  unsigned char*…

Continue ReadingEnhancing Images using Native functions in Phimpme Android

Storing a Data List in Phimpme Android

In Phimpme Android, it is required to store all the available camera parameters like a list of ISO values, available camera resolution etc. so that it can be displayed to the user in the camera settings. In Phimpme, we have stored these list of data in SharedPreferences with some modifications. As we cannot store a list directly in SharedPreference, in this post I will be discussing how we achieved this in Phimpme Android application. To store the ArrayList you have to create a function that will convert the array into a string by using some symbol. Step - 1 First, Create a class say TinyDB which contains functions to store an array in sharedPreferences. public class TinyDB { private SharedPreferences preferences; public TinyDB(Context appContext) { preferences = PreferenceManager.getDefaultSharedPreferences(appContext); } } Step - 2 Create functions to convert the array into string and store in sharedPreferences. putListInt() method will convert the string ArrayList to String and store in sharedPreferences. Similarly, putListString() method will convert the integer ArrayList to string and store in sharedPreferences. public void putListInt(String key, ArrayList<Integer> intList) {   if (key == null) return;   if (intList==null) return;   Integer[] myIntList = intList.toArray(new Integer[intList.size()]);   preferences.edit().putString(key, TextUtils.join("‚‗‚", myIntList)).apply(); }    public void putListString(String key, ArrayList<String> stringList) {   if (key == null) return;   if (stringList ==null)return;   String[] myStringList = stringList.toArray(new String[stringList.size()]);   preferences.edit().putString(key, TextUtils.join("‚‗‚", myStringList)).apply(); }     Now create the object of TinyDB.class to call the above functions using tinyDb object. Now our data is saved in sharedPreference to get this data we have to create a getter for the ArrayList.   Step-3 Add two functions in TinyDB.class to get the string and integer ArrayList. public ArrayList<String> getListString(String key) {         return new ArrayList<String>(Arrays.asList(TextUtils.split(preferences. =getString(key, ""), "‚‗‚"))); } public ArrayList<Integer> getListInt(String key) {   String[] myList = TextUtils.split(preferences.getString(key, ""), "‚‗‚");   ArrayList<String> arrayToList = new ArrayList<String>(Arrays.asList(myList));   ArrayList<Integer> newList = new ArrayList<Integer>();   for (String item : arrayToList)       newList.add(Integer.parseInt(item));   return newList; } Now to get the saved integer and string ArrayList simply call this function by creating an instance of TinyDB.class. The below screenshot depicts how we have stored the list of camera resolutions in SharedPreference using TinyDB class. So this is how you can store the entire ArrayList in sharedPreferences. For more detail, you can see the TinyDb.class in our Phimpme project. Resources:   https://stackoverflow.com/questions/7057845/save-arraylist-to-sharedpreferences http://blog.nkdroidsolutions.com/arraylist-in-sharedpreferences/ http://findnerd.com/list/view/Save-ArrayList-of-Object-into-Shared-Preferences-in-Android/510?page=10&ppage=3 https://github.com/fossasia/phimpme-android/blob/development/app/src/main/java/org/fossasia/phimpme/opencamera/Camera/TinyDB.java    

Continue ReadingStoring a Data List in Phimpme Android

Iteration through the Android File System in the phimpme project

Android uses the single file system structure which has a single root. The task involved creating a custom folder chooser to whitelist folders while displaying images in the gallery in the Phimpme Photo App. The challenge arose in iterating over the files in the most efficient way. The best possible way to represent the file structure is in the form of tree data structure as given below. Current Alternative Currently, the MediaStore class contains metadata for all available media on both internal and external storage devices. Since it only returns a list of a particular media file format, it refrains the developer from customizing the structure in his way. Implementation Create a public class which represents the file tree. Since each subtree of the tree could itself be represented as file tree itself, therefore the parent of a node will be a FileTree object itself. Therefore declare a list of FileTree objects as children of the node, a FileTree object as the parent of the particular node, node’s own File object along with string values filepath and display name associated with it. public class FileTree {  public final String filepath;  public final String displayName;  public final List<FileTree> childFileTreeList = new ArrayList<>();  public final FileTree parent;  public boolean hasMedia = false;  public FileTree(String filepath, String displayName, FileTree parent) {     this.filepath = filepath;     this.displayName = displayName;     this.parent = parent;  } } For iterating through the file system, we create a recursive function which is called on the root of the Android file system. If the particular file is a directory, with the help of Depth First traversal algorithm, the directory is traversed. Else, the file is added to the list of the file. The below code snippet is the recursive function. public static void walkDir(FileTree fileTree, List<File> files) {   File listFile[] = fileTree.file.listFiles();   if (listFile != null) {       for (File file : listFile) {           if (file.isDirectory()) {               FileTree childFileTree = new FileTree(file, file.getName(), fileTree);               fileTree.childFileTreeList.add(childFileTree);               walkDir(childFileTree, files);           }           else {                   files.add(file);           }       }   } } Conclusion The android file system was used to whitelist folders so that the images of the folders could neither be uploaded nor edited. For the complete guide to whitelisting folders, navigate here

Continue ReadingIteration through the Android File System in the phimpme project

Native Functions for Performing Image Processing in Phimpme Android

In Android, image processing can be performed using Java or RenderScript or Native(C/C++). The performance of native code(C/C++) for image processing is much better than Java and RenderScript. So we used native code for image processing in the photo editor of the Phimpme image application. In this blog, I explain how image processing is performed in Phimpme Android. Setting up build script for native code. NDK helps us to develop Android applications using native languages like C and C++ so that heavy tasks can be performed in relatively less time. We can also use libraries built using C/C++ in Android application using this NDK. NDK can be downloaded using the SDK manager of Android Studio and can be set up following instructions in Android developers’ site. After setting up the NDK, we will create a simple application involving native code and understand the flow of functions from Java to native. The java files are present in app/src/main/java directory. Similarly, all the native files are present in app/src/main/jni directory. So now let’s create necessary files in jni directory. main.c - Native functions are added here Android.mk and Application.mk - make files for building native code using ndkbuild. Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := main.c       // include the files that should be                                // built(.c, .cpp, .h) LOCAL_LDLIBS += -llog LOCAL_MODULE := modulename      //name of the module (custom) include $(BUILD_SHARED_LIBRARY) Application.mk APP_OPTIM := release APP_ABI := all                    //architectures for which native lib //has to be built(can be one or many.                               //should be separated by comma) APP_PLATFORM := android-25 Add these lines to app’s build.gradle for building native code along with the Gradle build. externalNativeBuild {   ndkBuild {       path 'src/main/jni/Android.mk'   } } The above lines in build.gradle will run Android.mk during the Gradle build. When the Android.mk runs, it compiles all native code and generates modulename.so files in .externalNativeBuild/ndkBuild directory for all the mentioned architectures. This .so file for a particular architecture is a library containing all the native code compatible with that architecture. So when this library(.so file) is statically imported into Java code, native code gets linked to Java and enables calling native functions directly from Java. Importing native Library into Java Static import of this library can be done by writing the below lines in your Java class. static { System.loadLibrary("modulename"); } Creating a native function and calling it from Java? Unlike normal java code, where you call a function by its name, here in native Android development, the name of the native function is different from what you call it in java. To understand this clearly, let’s see an example of simple hello world application. Define the native function in Java and call it normally like any other function. package org.fossasia.phimpme; import … public class MainActivity extends Activity {   @Override   public void onCreate(Bundle savedInstanceState) {       super.onCreate(savedInstanceState);       setContentView(R.layout.activity_main);              textView = (TextView)findViewById(R.id.textview);       textView.setText(helloworld());   }    static {        System.loadLibrary(“modulename”);    }     Public native String helloworld(); } Here the definition of the native function is present in org.fossasia.phimpme package and MainActivity class.…

Continue ReadingNative Functions for Performing Image Processing in Phimpme Android

Implementing UNDO and REDO in Image Editor of Phimpme Android

The main feature in any image editor application like Phimpme Android other than editing the image is the ability to revert the changes (UNDO) that are done and the ability to revert the reversion i.e reperform the changes (REDO). In Phimpme Application, we implemented this by using an ArrayList of Bitmaps. We stored the copy of the image bitmap whenever the modification is done on it. This helped us to get back to the previous image when required. But there is a problem in this method. They method may produce OutOfMemory Error when storing the bitmap in ArrayList when memory gets full. So for dealing solving this in the Phimpme application, we added a try - catch block and when the out of memory exception is caught, we recycled and removed the initial modified image from list i.e the image of index 1 in ArrayList. Index 0 is the original image on which we are working on. When we recycled that image, it gives space for adding another image, So added the recent image at the end of the list. addToUndoList() function is shown below. private void addToUndoList() {   try{       recycleBitmapList(++currentShowingIndex);       bitmapsForUndo.add(mainBitmap.copy(mainBitmap.getConfig(),true));   }catch (OutOfMemoryError error){       bitmapsForUndo.get(1).recycle();       bitmapsForUndo.remove(1);       bitmapsForUndo.add(mainBitmap.copy(mainBitmap.getConfig(),true));   } } In the above function, bitmapsForUndo is ArrayList in which we added modified bitmaps in the editor of Phimpme application. mainBitmap is the image bitmap on which all modifications are being done in the editor. The sense of integer variable currentShowingIndex is clear from its name that it points to the index of the image that is currently getting shown. Eg. Consider a case when you perform 5 edits on an image using Phimpme Editor, then 6 image bitmaps get stored in the ArrayList including the original image and currentShowingIndex will be 5. Now if you undo the steps twice the currentShowingIndex becomes 3. The bitmaps of the index 4 and 5 have not been removed from the ArrayList yet. So they will be useful if you want to redo the changes.    When you make an another edit, an image bitmap gets added at index 4 and that should be the last element of the ArrayList. But you see that there is a bitmap of index 5 making that the last element of the ArrayList, not the newly added one. So in order to achieve that, the elements present in the ArrayList whose index is greater than currentShowingIndex have to recycled and removed before adding a newly modified image bitmap to the ArrayList. The first line in the try block of the above functions is referring to the function that is going to implement this. That function’s implementation is given below private void recycleBitmapList(int fromIndex){   while (fromIndex < bitmapsForUndo.size()){       bitmapsForUndo.get(fromIndex).recycle();       bitmapsForUndo.remove(fromIndex);   } } Removing the bitmap from the ArrayList doesn’t clear the memory. That bitmap has to be recycled before getting removed from the ArrayList which is performed in the above function of the Phimpme application’s image editor.  The above recycleBitmapList function recycles and removes the bitmaps which have an…

Continue ReadingImplementing UNDO and REDO in Image Editor of Phimpme Android

Implementing a zoomable ImageView by Extending the Default ViewPager in Phimpme Android

When I was trying to give default gallery-like experience to the gallery of Phimpme Image Application, where you can zoom an image with pan and pinch controls along with the ability to navigate to another photo by swipe gestures, I faced a problem in which when the zoomed image is swiped expecting it to get panned, instead of that, the viewpager switched to another page. This implementation of Viewpager with zoomable image in it might seem straightforward in the beginning but once you start implementing this in most common way i.e using default ViewPager for navigation between images and zooming libraries like TouchImageView, subsampling-scale-image-view or PhotoView for zooming the image with pinch and pan controls, you will notice that when you swipe left or right on the zoomed image, the pager navigates to other images instead of the zoomed image getting panned. The viewpager responds to the swipe event and causes page change and it doesn’t let zoomable view to respond to that event. In the above screenshot, front image is zoomed and when we swipe left, instead of the image getting panned, it is switching to next page. How to solve this? As the problem is caused by the default ViewPager utilizing the swipe event without transferring it to child views, a custom viewpager can be created by extending default viewpager and having a touch intercept method which transfers the event to its child views. A sample implementation of this custom view pager which I used in the app is shown below. public class CustomViewPager extends ViewPager { public CustomViewPager(Context context) {   super(context); } public CustomViewPager(Context context, AttributeSet attrs) { super(context,attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) {   try {   return super.onInterceptTouchEvent(ev); } catch (IllegalArgumentException e) {    return false;   } } } Now we can replace normal viewpager with this custom view pager in image viewing activity and layout resource for that activity. The normal pager adapter which is used with default view pager can be used with this custom viewpager also. You can get a clear understanding of what I described here by having a look at the below implementation. activity_imageview.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout   xmlns:android="http://schemas.android.com/apk/res/android"   android:layout_width="match_parent"   android:layout_height="match_parent">   <package.name.path.to.CustomViewPager       android:id="@+id/cviewpager"       android:layout_width="match_parent"       android:layout_height="match_parent"/> </RelativeLayout> ImageViewActivity.java public class ImageViewActivity extends Activity { CustomViewPager cViewPager; ArrayList<String> imageList; @Override public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_imageview);        imageList = createList(); //some method for creating a list        cViewPager = (CustomViewPager)findViewById(R.id.cviewpager);          mViewPager.setAdapter(new ImagePagerAdapter(imageList)); } class ImagePagerAdapter extends PagerAdapter { ArrayList<String> imageList;         ImagePagerAdapter(ArrayList<String> imageList){ this.imageList = imageList;    }    @Override   public int getCount() {    return (null != imageList) ? imageList.size() : 0;   }    @Override   public boolean isViewFromObject(View view, Object object) {   return view == object;     }   @Override   public View instantiateItem(ViewGroup container, int position) {    PhotoView photoView = new PhotoView(container.getContext()); Glide.with(getContext())        .load(UriFromFile(new File(imageList.get(position))))        .asBitmap()        .thumbnail(0.2f)        .into(photoView); photoView.setMaximumScale(5.0F);          photoView.setMediumScale(3.0F);     container.addView(photoView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);     return photoView;   }   @Override   public void destroyItem(ViewGroup container, int position, Object…

Continue ReadingImplementing a zoomable ImageView by Extending the Default ViewPager in Phimpme Android

Adding Multiple Themes in Phimpme Android

In Phimpme-Android we decided to add a new feature that is providing multiple themes to the users. We have 3 types of themes in Phimpme Dark Theme, Light Theme and Amoled Theme. In this post, I am explaining how I added multiple themes support in phimpme android.  Choose Theme in Phimpme Dialog You need a Helper class that will store the data about the theme and all the colors related to a theme. Before you begin you need to create a Helper class. In Phimpme I created a Helper class as ThemeHelper public class ThemeHelper { public static final int DARK_THEME = 2; public static final int LIGHT_THEME = 1; public static final int AMOLED_THEME = 3; private PreferenceUtil SP; private Context context; private int baseTheme; private int primaryColor; private int accentColor; public ThemeHelper(Context context) {  this.SP = PreferenceUtil.getInstance(context);  this.context = context;  updateTheme(); } } Which contains all the basic method to get colors for textview, icon, toolbar, switch, imageview, background and app primary color. Now you to provide user to select theme and it can be done using dialog box. Once the user selected any of the theme we have to update that theme and it can be done by following code : public void updateTheme(){  this.primaryColor = SP.getInt(context.getString(R.string.preference_primary_color),        getColor(R.color.md_light_blue_300));  this.accentColor = SP.getInt(context.getString(R.string.preference_accent_color),        getColor(R.color.md_light_blue_500));  baseTheme = SP.getInt(context.getString(R.string.preference_base_theme), LIGHT_THEME); } Now we have updated the our theme in Phimpme now we have to set the color according to a theme. To get colors of all components we need to add some function in our helper class which will provide us the colors according to the theme. As I said we are having 3 themes in Phimpme so I used 3 case to compare which theme user has selected. I have added the functions to get colors for background, text and subtext as follows in phimpme. public int getBackgroundColor(){  int color;  switch (baseTheme){    case DARK_THEME:color = getColor(R.color.md_dark_background);break;    case AMOLED_THEME:color = getColor(R.color.md_black_1000);break;    case LIGHT_THEME:    default:color = getColor(R.color.md_light_background);  }  return color; } public int getTextColor(){  int color;  switch (baseTheme){    case DARK_THEME:color = getColor(R.color.md_grey_200);break;    case AMOLED_THEME:color = getColor(R.color.md_grey_200);break;    case LIGHT_THEME:    default:color = getColor(R.color.md_grey_800);  }  return color; } public int getSubTextColor(){  int color;  switch (baseTheme){    case DARK_THEME:color = getColor(R.color.md_grey_400);break;    case AMOLED_THEME:color = getColor(R.color.md_grey_400);break;    case LIGHT_THEME:    default:color = getColor(R.color.md_grey_600);  }  return color; } In the above functions, I am comparing which theme user has selected and returned the color according to the theme. Now set the color to text by using above function you don’t need care which theme user has selected because those function will check and return the color according to the theme. So it can be done simply, textview.setTextColor(getTextColor()); editText.setTextColor(getTextColor()); editText.setHintTextColor(getSubTextColor()); -                                      Light Theme &  Dark Theme (Phimpme) Resources: https://github.com/fossasia/phimpme-android/blob/development/app/src/main/java/org/fossasia/phimpme/leafpic/util/ThemeHelper.java http://www.hidroh.com/2015/02/16/support-multiple-themes-android-app/

Continue ReadingAdding Multiple Themes in Phimpme Android

Preparing a release for Phimpme Android

Most of the essential features are now in a stable state in our Phimpme Android app. So we decided to release a beta version of the app. In FOSSASIA we follow branch policy where in development all current development will take place and in master branch the stable code resides. Releasing an app is not just building an apk and submitting to the distribution platform, certain guidelines should follow. How I prepare a released apk for Phimpme List down the feature We discussed on our public channel what features are now in stable state and can be released. Features such as account manager and Share Activity is excluded because it is not complete and in under development mode. We don’t want to show and under development feature. So excluded them. And made a list of available features in different category of Camera, Gallery and Share. Follow the branch policy. The releasable and stable codebase should be on master branch. It is good to follow the branch policy because it helps if we encounter any problem with the released apk. We can directly go to our master branch and check there. Development branch have very volatile because of active development going on. Every Contributor’s contribution is important When we browse our old branches such as master in case of ours. We see generally it is behind 100s of commits to the development. In case of that when we create a PR for that then it generally contains all the old commits to make the branch up to the latest. In this case while opening and merging do not squash the commits. Testing from Developer’s end Testing is very essential part in development. Before releasing it is a good practice that Developer should test the app from their end. We tested app features in different devices with varying Android OS version and screen size. If there is any compatibility issue, report it right away and there are several tools in Android to fix. Support variety of devices and screen sizes Changing package name, application ID Package name, application ID are vitals of an app. Which uniquely identifies them as app in world. Like I changed the package name of Phimpme app to org.fossasia.phimpme. Check all the permission app required. Create Release build type Build types are great to way categorize the apps. Debug and Release are two. There are various things in codebase which we want only in Debug modes. So when we create Release mode it neglect that part of the code. Add build types in you application build.gradle buildTypes {   release {       minifyEnabled false   } Rebuild app again and verify from the left tab bar Generate Signed apk and Create keystore (.jks) file Navigate to Build → Generate Signed APK Fill all details and proceed further to generate the signed apk in your home directory. Adding Signing configurations in build.gradle Copy the keystore (.jks) file to the root of the project and add signing configurations signingConfigs {       config {           keyAlias 'phimpme'…

Continue ReadingPreparing a release for Phimpme Android

Adding Stickers Feature on Phimpme Android App with ViewFlipper and Scrollview

For any image editing application stickers play an important role in editing an image. Phimpme is no different. There can be many different kinds of stickers. As Phimpme is an Open Source application. The user can add their own stickers to be implemented on Phimpme. But this gives a long and non-exhaustive list of stickers that the user has to go through. Sorting the stickers into different categories is one way of doing it. It provides quick access to the desired sticker a user wants to add to her or his photo. In order to achieve this, I am using ViewFlipper and Scrollview. Categorizing the types of Stickers. How it is done in Phimpme? Currently, there are six different categories for stickers. Namely: Facial, Hearts, Objects, Comments, Wishes, Animals. The following code is used to store the category name: public static final String[] stickerPath = {"stickers/type1", "stickers/type2", "stickers/type3", "stickers/type4", "stickers/type5", "stickers/type6"}; public static final String[] stickerPathName = {"Facial", "Hearts", "Objects", "Comments", "Wishes", "Animals"};   We need to populate the sticker fragment with the different categories. This is done by overriding onBinderHolder() function and using ImageHolder to handle onClickListener. private ImageClick mImageClick = new ImageClick(); Getting the position of the stickerPathName and setting it in stickerFragment. @Override    public void onBindViewHolder(ViewHolder holder, int position) {        ImageHolder imageHoler = (ImageHolder) holder;        String name = stickerPathName[position];        imageHoler.text.setText(name);        imageHoler.text.setTag(stickerPath[position]);        imageHoler.text.setOnClickListener(mImageClick);    }   Adding Stickers to the different categories. Now that we have different categories, we can assign different types of stickers to specific categories. We are using RecyclerView.Adapter<ViewHolder>, which implements onCreateViewHolder() method. onCreateViewHolder method is created every time we need a new view, hence RecyclerView comes handy in such situation rather than a normal list. First, we need to define the xml file where each sticker will be displayed in the form of ImageView. This ImageView has specific maxHeight and maxWidth for a uniform view. The xml file name is: view_sticker_item.xml <ImageView xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/img"    android:layout_width="wrap_content"    android:layout_height="match_parent"    android:maxHeight="50dp"    android:maxWidth="50dp"    android:paddingLeft="5dp"    android:paddingRight="5dp"    android:scaleType="centerInside" /> After we set up view_sticker_item.xml, we have to inflate it. @Override    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewtype) {        View v = null;        v = LayoutInflater.from(parent.getContext()).inflate(                R.layout.view_sticker_item, parent, false);        ImageHolder holder = new ImageHolder(v);        return holder;    }   I have saved all the images in the assets folder and distributed it among type1, type2, type3, type4, type5 and type6. One thing is to be kept in mind that the images should be in png format. PNG format images are only pixelated on the required areas. So that it does not hamper the background of the image. Displaying stickers Displaying sticker are done by overriding onBindViewHolder again. It accepts two parameters: ViewHolder holder and int position. ImageHolder is used to set the image of the sticker and then handling it by onClickListner(). @Override    public void onBindViewHolder(ViewHolder holder, int position) {        ImageHolder imageHoler = (ImageHolder) holder;        String path = pathList.get(position);        ImageLoader.getInstance().displayImage("assets://" + path,                imageHoler.image, imageOption);        imageHoler.image.setTag(path);        imageHoler.image.setOnClickListener(mImageClick);    }   public void addStickerImages(String folderPath) {        pathList.clear();        try {            String[] files = mStirckerFragment.getActivity().getAssets()                    .list(folderPath);            for (String name…

Continue ReadingAdding Stickers Feature on Phimpme Android App with ViewFlipper and Scrollview