Friday, 30 June 2017

Android: Sending headers with HttpURLConnection

This post includes the usage and implementation of HttpURLConnection to download a file from a URL along with sending the required headers with the http request. Through this post you will also learn to send custom headers along with the request to your http url.

The usage and implementation of HttpURLConnection is very simple as follows:

1. In your project, just add the following method where you want to download the file. Just pass the url from which you want to download the file, as the parameter to the below method.

private void downloadFileFromHttpURL(String your_url){
            
            URL url = new URL(your_url);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // default headers for the request
            connection.addRequestProperty("Content-Type", "application/json");

            // custom headers for the request
            connection.addRequestProperty("customHeaderKey1", "HEADER_VALUE");
            connection.addRequestProperty("customHeaderKey2", "HEADER_VALUE");

            // check for the connection of url
            int response = connection.getResponseCode();
            if (response == 200) { // connected to the URL
LogWriter.write("LOG_TAG", "Is downloading..?");     

BufferedInputStream inStream = new BufferedInputStream(connection.getInputStream());
                // provide the path to save the downloaded file
                FileOutputStream fileStream = new FileOutputStream("YOUR_FILE_PATH");

                // BufferesOutputStream is used to write the downloaded file
                BufferedOutputStream outStream = new BufferedOutputStream(fileStream);

                byte[] buffer = new byte[16384];
                int len = 0;
                while ((len = inStream.read(buffer, 0, 16384)) != -1) {
                    LogWriter.write("LOG_TAG", "Yes downloading..");
                    outStream.write(buffer, 0, len);
                }
                outStream.flush();
                inStream.close();
                outStream.close();
            } else {
                // disconnect from URL if not connected  
                connection.disconnect();
                return null;
            }
            // disconnect from URL when the download is completed  
            connection.disconnect();
    }

That's all.
The above method will download the file from the url and save it to the path provided by you.
There are other option as well that you can use with HttpURLConnection which are follows:
   
      connection.setUseCaches(false);
      connection.setDoInput(true);
      connection.setDoOutput(true);
      connection.setRequestMethod("POST");

Note:
HttpURLConnection uses the GET method by default. It will use POST if setDoOutput(true) has been called.
Other HTTP methods (OPTIONS, HEAD, PUT, DELETE and TRACE) can be used with setRequestMethod(String).


Share and comment if any issues.

Monday, 26 June 2017

Android: Add and remove view dynamically

In this post I will show you how to add and remove a view dynamically at run-time.
This will be explained in a very simple activity in which when you will click the Add button, a new View will be added in the main layout(screen visible to you), and when you will click the Remove button, the newly added view will be removed from the main layout.


1. First of all make a layout class for the view which you want to inflate at run time. Here I'm naming it as row.xml and add the following code to it:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <Button
        android:id="@+id/remove"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Remove"/>
    <TextView
        android:id="@+id/textout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@+id/remove"/>
</RelativeLayout>


2. Now in the MainActivity.java class just add the below code snippet:

public class MainActivity extends Activity {

 EditText textIn;
 Button buttonAdd;
 LinearLayout container;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  textIn = (EditText)findViewById(R.id.textin);
  buttonAdd = (Button)findViewById(R.id.add);
  container = (LinearLayout)findViewById(R.id.container);
  
  buttonAdd.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
// code to inflate the view to be added at run time (row.xml)    
LayoutInflater layoutInflater = 
      (LayoutInflater) getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final View addView = layoutInflater.inflate(R.layout.row, null);
    TextView textOut = (TextView)addView.findViewById(R.id.textout);
    textOut.setText(textIn.getText().toString());
    Button buttonRemove = (Button)addView.findViewById(R.id.remove);
    buttonRemove.setOnClickListener(new OnClickListener(){

     @Override
     public void onClick(View v) {
      ((LinearLayout)addView.getParent()).removeView(addView);
     }});
    
    container.addView(addView);
   }});
  
 }
}

3. The layout file for MainActivity.java class named activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="Add"/>
        <EditText
            android:id="@+id/textin"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_toLeftOf="@+id/add"/>
    </RelativeLayout>
    <LinearLayout 
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    </LinearLayout>

</LinearLayout>

That's all. Compile and run the app and after pressing the Add button you can see that a new view is added below to the Add button.


Share and comment if any issue.

Sunday, 18 June 2017

Android: ExpandableListView item click in Activity

In this post I will show the implementation of getting the item click event of ExpandableListview in your calling Activity or Fragment.
ExpandableListView is used to group list data by categories.It is a view that shows items in a vertically scrolling two-level list. It differs from a ListView by allowing two levels which are groups that can be easily expanded and collapsed by touching to view and their respective children items.
If you are not familiar with using ExpandableListView, first refer the tutorial here.

Now to get the item click in your activity or fragment follow below steps:

1. First make an Interface for the connectivity of your item click in your activity. For this create a class IExpandableListItemClick.java and add the following code:

public interface IExpandableListItemClick {

    void onExpandedItemClick(View view, int position);

}

2. In your adapter class make a variable for your Interface as follows:

 private IExpandableListItemClick expandedItemClickListener;

3. Now in the constructor of your adapter class assign your interface as follows:

public ExpandableListAdapter(Context context, List<String> expandableListTitle, HashMap<String, String>> expandableListDetail,
                          IExpandableListItemClick listener) {
        this.context = context;
               ................                                             
        this.expandedItemClickListener = listener;
    }


4. Now in the getChildView method of your adapter class add the following code:

 @Override
    public View getChildView(int listPosition, int expandedListPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(context);
        convertView = inflater.inflate(R.layout.item_child_expandable_list, parent, false);
        
        // declare and initialize your view here

        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                expandedItemClickListener.onExpandedItemClick(view, expandedListPosition);
            }
        });
        return convertView;
    }

5. Now in your activity or your fragment implement your interface as follows: I am using a fragment
and implement its method.

public class MainFragment extends Fragment implements IExpandableListItemClick {

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
                                                     
          .......... ...............                 
                                                     
        return rootView;
    }                            
  ..... .........                 

@Override
    void onExpandedItemClick(View view, int position){   
                                                                                             
     }                                                                                      
 ...........                                                                                 
                                                                                             
}                

6. Now in the above method add a toast to see which item is clicked as follows:

@Override
    void onExpandedItemClick(View view, int position){                        
        Toast.makeText(getActivity, "Clicked item position: "+ position, Toast.LENGTH_SHORT).show();  
                                                         
     }


7. Now run your code and you can see the correct position of the item clicked in the toast.
You can change the parameters in interface method according to your requirements.

That's all.
Share it and comment if any issues.

Sunday, 11 June 2017

Android: BigPictureStyle Notification

Now a days, you must have seen a notification from many android apps that contain a picture/image along with the message. This notification with a big image is known as BigPicturestyle Notifications. These notifications are generally used for the promotional purpose of some brand or some product or you can say about an offer.
With help of V4 appcompat library, we can implement this for all devices from Android 2.0 onward.
Building this type of notification in android is very simple and can be implemented as follows:

1. First create Notification object and set the title, content text, ticker text etc as follows:
        
        //Create notification object and set the content.
        NotificationCompat.Builder nb= new NotificationCompat.Builder(this);
        nb.setSmallIcon(R.drawable.small_icon);
        nb.setContentTitle("Notification title");
        nb.setContentText("Notification content/message");
        nb.setTicker("Notification ticker text");

2. Now create a bitmap of the image which needs to be shown as big picture & set it as shown in below code. Set the summaryText, this will appear on expanding the notification.
        
        //get the bitmap to show in notification bar
        Bitmap bm = BitmapFactory.decodeResource(this.getResources(),R.drawable.big_icon);
        NotificationCompat.BigPictureStyle s = new NotificationCompat.BigPictureStyle().bigPicture(bm);
        s.setSummaryText("Notification text that appears on expanding the notification");
        nb.setStyle(s);

3. Now set the intent that should be launched on clicking on the notification.
        Intent resultIntent = new Intent(this, MainActivity.class);
        TaskStackBuilder taskBuilder = TaskStackBuilder.create(this);
        taskBuilder.addParentStack(MainActivity.class);
       
        // Adds the Intent that starts the Activity to the top of the stack
        taskBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent =
                taskBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
        nb.setContentIntent(resultPendingIntent);
        nb.setAutoCancel(true);
        NotificationManager mNotificationManager =
                (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
        // mId allows you to update the notification later on.
        mNotificationManager.notify(11221, nb.build());

That's all.
Share and comment if any issues.


Sunday, 4 June 2017

Android: CoordinatorLayout

In this post I will let you know about the new layout introduced in Android Design Support Library.
The CoordinatorLayout is a super-powered FrameLayout. It is similar to Frame Layout yet its behavior attribute makes it different from other layouts. If you have used a FrameLayout before, you should be very comfortable using CoordinatorLayout. If you haven’t used a FrameLayout, do not worry, it is pretty straightforward.

CoordinatorLayout is intended for two primary use cases:
- As a top-level application decor or chrome layout
- As a container for a specific interaction with one or more child views

By specifying Behaviors for child views of a CoordinatorLayout you can provide many different interactions within a single parent and those views can also interact with one another. View classes can specify a default behavior when used as a child of a CoordinatorLayout using the DefaultBehavior annotation.

Behaviors may be used to implement a variety of interactions and additional layout modifications ranging from sliding drawers and panels to swipe-dismissable elements and buttons that stick to other elements as they move and animate.

Children of a CoordinatorLayout may have an anchor. This view id must correspond to an arbitrary descendant of the CoordinatorLayout, but it may not be the anchored child itself or a descendant of the anchored child. This can be used to place floating views relative to other arbitrary content panes.

Children can specify insetEdge to describe how the view insets the CoordinatorLayout. Any child views which are set to dodge the same inset edges by dodgeInsetEdges will be moved appropriately so that the views do not overlap.

-Dependency:
For using CoordinatorLayout in you app import Android Support Library into your project, by adding the following dependency to your app build.gradle file:

           dependencies {
               ......
                   compile 'com.android.support:design:23.0.0'
          }

Above Support Library also includes others views namely Snackbar, CollapsingToolbar, FloatingActionButton etc out of which some of them we will be using today.

1. To show the use of CoordinatorLayout, we will simply make layout containing a FAB button which will automatically slides out of the way when a Snackbar is displayed. The CoordinatorLayout is the root layout. Within it, we have a button, that is centered on screen, and a FAB, that’s positioned at the bottom right of the screen, with a little margin to ensure we abide by the material design guidelines.
The layout class is as follows:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.sample.foo.usingcoordinatorlayout.FabAndSnackbarActivity">

    <Button
        android:id="@+id/showSnackbarButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/show_snackbar"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:src="@android:drawable/ic_popup_disk_full"/>

</android.support.design.widget.CoordinatorLayout>

2. Now create a class FabAndSnackbarActivity.java and add the following code:

public class FabAndSnackbarActivity extends AppCompatActivity {

    private Button mShowSnackbarButton;
    private CoordinatorLayout mCoordinatorLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fab_and_snackbar);

        mCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);

        mShowSnackbarButton = (Button) findViewById(R.id.showSnackbarButton);
        mShowSnackbarButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(mCoordinatorLayout,
                        "This is a simple Snackbar", Snackbar.LENGTH_LONG)
                        .setAction("CLOSE", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                // Custom action
                            }
                        }).show();
            }
        });
    }
}

3. Now compile it and run your program. You will observe that the FAB button automatically slides up and out of the way for the Snackbar, when it is shown, and slides down and back to it’s position, when the snackbar is exiting from view. 

That's all. Share and comment if any issues.


Saturday, 27 May 2017

Android: GridView as ExpandableListView Item

In this post I will show you how to use a GridView as the item of an ExpandableListView.
An ExpandableListView is a view that shows items in a vertically scrolling two-level list.
This differs from the ListView by allowing two levels: one are the groups and other are the child items. The Groups can individually be expanded to show its children.

Now the implementation of using a GridView as an item of ExpandableListView is as follows:

1. First of all make a custom gridView class named MyCustomGridView.java and add the following code snippet to it:

public class MyCustomGridView extends GridView {

    private final Context mContext;
    int mHeight;

    public MyCustomGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
    }

    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int desiredWidth = 100;
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int width;
        // Measure Width
        if (widthMode == MeasureSpec.EXACTLY) {
            // Must be this size
            width = widthSize;
        } else if (widthMode == MeasureSpec.AT_MOST) {
            // Can't be bigger than...
            width = Math.min(desiredWidth, widthSize);
        } else { // Be whatever you want
            width = desiredWidth;
        }
        // MUST CALL THIS
        setMeasuredDimension(width, mHeight);
        getGridViewSpanCount(width, mHeight);
    }

    public void setGridViewItemHeight(int height) {
        mHeight = height;
    }
}

2. Now make the layout file named gridview_item.xml which will be used as item of GridView:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/item_gridView_imgView"
        android:layout_width="@dimen/dimen_img_width"
        android:layout_height="@dimen/dimen_img_height"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/item_gridView_txtView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:textAlignment="center"
        android:textColor="@color/black"
        android:textSize="16sp" />

</RelativeLayout>

3. Now make the adapter named MyCustomGridViewAdapter.java for setting the views in your gridView as follows:

public class MyCustomGridViewAdapter extends BaseAdapter {

    private Context mContext;
    private final ArrayList<YOUR_CLASS_TYPE> arrayList;

    public MyCustomGridViewAdapter(Context context, ArrayList<YOUR_CLASS_TYPE> arrayList) {
        this.mContext = context;
        this.arrayList = arrayList;
    }

    @Override
    public int getCount() {
        return arrayList.size();
    }

    @Override
    public YOUR_CLASS_TYPE getItem(int position) {
        return arrayList.get(position);
    }

    @Override
    public long getItemId(int arg0) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.gridview_item, parent, false);
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.item_gridView_txtView);
            holder.imageView = (ImageView) convertView.findViewById(R.id.item_gridView_imgView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.text.setText(arrayList.get(position).getName());
  // Glide is the library used to laod an image into an imageView
        Glide.with(mContext).load(arrayList.get(position).getThumbnail_url())
                .asBitmap().centerCrop()
                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                .into(holder.imageView);
        return convertView;
    }

    private static class ViewHolder {
        TextView text;
        ImageView imageView;
    }
}

4. Now create a Fragment named ExpandableListViewFragment.java and add the following code snippet:

public class ExpandableListViewFragment extends Fragment implements GridViewItemClickInterface {

    private List<String> listDataHeader;
    private HashMap<String, ArrayList<YOUR_CLASS_TYPE>> listDataChild;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.layout_fragment_expandable_listvw, container, false);

        ExpandableListView mExpandablelistView = (ExpandableListView) rootView.findViewById(R.id.fragment_expandable_listview);
        prepareListData();
        CustomExpandableListAdapter mExpandableListAdapter = new CustomExpandableListAdapter(getActivity(), listDataHeader, listDataChild, this);
        mExpandablelistView.setAdapter(mExpandableListAdapter);
        mExpandablelistView.setOnGroupClickListener(new OnGroupClickListener() {
         @Override
         public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                // This way the expander cannot be collapsed
                // on click event of group item
                return false;
            }
        });
        return rootView;
    }

    private void prepareListData() {
        listDataHeader = new ArrayList<>();
        listDataHeader.add("Folder 1");
        listDataHeader.add("Folder 2");
        listDataChild = new HashMap<>();
        ArrayList<YOUR_CLASS_TYPE> details = new ArrayList<YOUR_CLASS_TYPE>();// fill the data as per your requirements
        listDataChild.put(listDataHeader.get(0), details);
        listDataChild.put(listDataHeader.get(1), null); // just to show null item view
    }

    @Override
    public void onGridViewItemClick(YOUR_CLASS_TYPE item) {
        Toast.makeText(getActivity(), "Currently selected is: " + item.getName(), Toast.LENGTH_SHORT).show();
    }
}

5. The layout file for the above fragment is as follows: layout_fragment_expandable_listvw.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

        <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ExpandableListView
            android:id="@+id/fragment_expandable_listview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:divider="@color/transparent"
            android:listSelector="@color/transparent" />

    </RelativeLayout>

</LinearLayout>

6. Now create the adapter named CustomExpandableListAdapter.java file with the following code snippet:

public class CustomExpandableListAdapter extends BaseExpandableListAdapter {

    private Context mContext;
    private List<String> mListDataHeader;
    private HashMap<String, ArrayList<YOUR_CLASS_TYPE>> mListDataChild;
    private LayoutInflater mInflater;
    private GridViewItemClickInterface gridViewItemClickListener;
    private int columnsCount = 3;

    public CustomExpandableListAdapter(Context context, List<String> listDataHeader, HashMap<String, ArrayList<YOUR_CLASS_TYPE>> listChildData, GridViewItemClickInterface listener) {
        this.mContext = context;
        this.mListDataHeader = listDataHeader;
        this.mListDataChild = listChildData;
        this.mInflater = LayoutInflater.from(context);
        this.gridViewItemClickListener = listener;
    }

    @Override
    public int getGroupCount() {
        return mListDataHeader.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return 1;
    }

    @Override
    public Object getGroup(int groupPosition) {
        return mListDataHeader.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return mListDataChild.get(this.mListDataHeader.get(groupPosition))
                .size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        String headerTitle = (String) getGroup(groupPosition);
        if (convertView == null) {
            // layout view of header group
            convertView = mInflater.inflate(R.layout.expandable_listvw_header, null);
        }
        TextView headerLabel = (TextView) convertView.findViewById(R.id.txtView_header);
        headerLabel.setTypeface(null, Typeface.BOLD);
        headerLabel.setText(headerTitle);
        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        convertView = mInflater.inflate(R.layout.expandable_listvw_item, null);
        final ArrayList<YOUR_CLASS_TYPE> items = mListDataChild.get(mListDataHeader.get(groupPosition));
        if (items.size() > 0) {
            MyCustomGridView gridView = (MyCustomGridView) convertView.findViewById(R.id.item_custom_gridView);
            gridView.setNumColumns(columnsCount);
            gridView.setVerticalSpacing(10);
            gridView.setHorizontalSpacing(10);
            MyCustomGridViewAdapter adapter = new MyCustomGridViewAdapter(mContext, items);
            gridView.setAdapter(adapter);
            int totalHeight = 0;
// This is to get the actual size of gridView at runtime while filling the items into it
            for (int size = 0; size < adapter.getCount(); size++) {
                RelativeLayout relativeLayout = (RelativeLayout) adapter.getView(size, null, gridView);
                relativeLayout.measure(0, 0);
                totalHeight += relativeLayout.getMeasuredHeight();
            }
            gridView.setGridViewItemHeight(v);
            gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    gridViewItemClickListener.onGridViewItemClick(items.get(position));
                }
            });
        } else {
            convertView = mInflater.inflate(R.layout.layout_blank, null);
        }

        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

}

7. The layout files for ExpandableListView group and item are as follows:
a) expandable_listvw_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/txtView_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/colorBlack"
        android:textSize="22sp" />

</LinearLayout>

b) expandable_listvw_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.nishant.sample.ExpandableListPac.MyCustomGridView
        android:id="@+id/item_custom_gridView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

c) layout_blank.xml - This is the layout to be shown when no items are available.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/item_txt_no_items"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:gravity="center_horizontal|center_vertical"
        android:text="No items available"
        android:textSize="22sp" />

</LinearLayout>

8. The interface class GridViewItemClickInterface.java is as follows:

public interface GridViewItemClickInterface {

    void onGridViewItemClick(YOUR_CLASS_TYPE item);
}

That's all. Now run your project and enjoy.

Share and comment if any issues.

Sunday, 21 May 2017

Android: Layout as background of view

In this post I will show you how to set your custom layout as the background of your item of your listview or gridview or any other view that contains long list of data, through your adapter.
This is very simple and can be done as follows:

1. Make a file custom_placeholder.xml of your custom layout as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="140dp"
    android:layout_height="140dp"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="6dp"
        android:background="@drawable/shape_bg">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="Downloading..."
            android:textAlignment="center"
            android:textSize="14sp" />

    </RelativeLayout>

</LinearLayout>


2. Now in the getView method of your adapter just replace your code with below code:

public View getView(final int position, View convertView, ViewGroup parent) {
        CustomViewHolder mViewHolder;
        if (convertView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = layoutInflater.inflate(R.layout.item_gridview_assets, parent, false);
            mViewHolder = new CustomViewHolder(convertView);  // set your layout (convertView) as your viewHolder
            convertView.setTag(mViewHolder);
        } else {
            mViewHolder = (CustomViewHolder) convertView.getTag();
        }
          //Now check the condition whether your image is available or not  
        String value = imageList.get(position);
        if (!value.equalsIgnoreCase("")) {
             // case when image is available  
           mViewHolder.imgAssets.setBackgroundResource(R.drawable.sample_img);
        } else {
             // case when image is not available  
           // This will inflate your custom view that you created above
            LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = layoutInflater.inflate(R.layout.custom_placeholder, parent, false);
        }
        return convertView;
    }

That's all.
Share and comment if any issues.



Sunday, 30 April 2017

Android: Capture screen as snapshot

This blog post is regarding how to capture your android screen as snapshot. This may be one of your requirements during the course of your application development. It is very simple to implement this functionality as follows:

1. On the click of your button or at the event at which you want to capture your screen just use the below method:

void onYourButtonClick() {
        try {
            LinearLayout layout = (LinearLayout) findViewById(R.id.layout);
            // pass your main layout id
            File screenshot = storeScreenShot(layout, "Screen_shot_" + new Date().getTime() + ".jpg");
            // you need to first save the captured image
        } catch (Exception ex) {
            ex.getMessage();
        }
    }

2. Method to save your file:

public static Bitmap getScreenShot(View view) {
        View screenView = view;
        screenView.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
        screenView.setDrawingCacheEnabled(false);
        return bitmap;
    }

    public static File storeScreenShot(View v, String fileName) {
        Bitmap bm = getScreenShot(v);
        final String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/SC";
        File dir = new File(dirPath);
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                Log.d("TAG", "Oops! Failed to create directory");
            }
        }
        File file = new File(dirPath, fileName);
        try {
            FileOutputStream fOut = new FileOutputStream(file);
            bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
            fOut.flush();
            fOut.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

3. So the file (screenshot) created in step one is your captured screen image file.
You can use this file as per your needs.


That's all.
Share and comment if any issues.

Sunday, 9 April 2017

Android: Snackbar example

Snackbar is one of the most interesting component introduced in Material Design. Snackbars are just like Toast messages except they provide action to interact with. Snackbar will be displayed at the bottom of the screen and can be swiped off in order to dismiss them.
Snackbars provide lightweight feedback about an operation. They show a brief message at the bottom of the screen on mobile and lower left on larger devices. Snackbars appear above all other elements on screen and only one can be displayed at a time.
They automatically disappear after a timeout or after user interaction elsewhere on the screen, particularly after interactions that summon a new surface or activity.
Snackbars can contain an action which is set via setAction(CharSequence, View.OnClickListener).

Also to be notified when a snackbar has been shown or dismissed, you can provide a Snackbar.Callback via addCallback(BaseCallback).


Implementing Snackbar is very simple which can be done as follows:

Snackbar snackbar = Snackbar
        .make(coordinatorLayout, "Snackbar is visible.", Snackbar.LENGTH_LONG)
        .setAction("DONE", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar snackbar1 = Snackbar.make(coordinatorLayout, "Snackbar dismissed.", Snackbar.LENGTH_SHORT);
                snackbar1.show();
            }
        });

snackbar.show();


One point to be noted here is that, while making a Snackbar I have used the CoordinatorLayout as the parent layout for Snackbar. Due to this CoordinatorLayout our Snackbar has the ability to be dismissed when swiped.


Tha's all.
Share and comment if any issues.


Thursday, 30 March 2017

Android: FileUriExposedException in Android N

If your android application shares files with/from other applications using Uri, and your application's targetSdkVersion is 24+ i.e Android N, then you may have encountered with an error/exception saying something like android.os.FileUriExposedException:

android.os.FileUriExposedException: file:///storage/emulated/0/DCIM/Camera/img_21032017190911.jpg exposed beyond app through ClipData.Item.getUri()

The error or exception is thrown when an application exposes a file:// Uri to another app.
Thus using file:// Uri is discouraged in this scenario because the receiving app may not have access to the path or the file:// Uri shared with it.
Like for example, the receiving app may not have requested the READ_EXTERNAL_STORAGE run time permission, or the platform may be sharing the file:// Uri across user profile boundaries, then this may result in an unexpected behaviour at best or at worst, it may result in a crash.

So the first thing to deal with this exception is that,

1. Your application should use content:// Uri instead of  file:// Uri so that the platform can extend temporary permission for the receiving app to access the resource.

2. Or you need to use FileProvider.

3. The work around from code can be done as follows:
    Just add the below code in your Application file's onCreate method as follows:

   public class ApplicationMain extends Application{

@Override
            public void onCreate() {
            super.onCreate();
....
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
....
}
   }


Note: This exception is only thrown for applications targeting N or higher. Applications targeting earlier SDK versions are allowed to share file:// Uri, but it's strongly discouraged.

That's all.
Share and comment if any issues.


Sunday, 26 March 2017

Android: Upload images using MultipartPost request

An HTTP MultipartPost request is a request that HTTP clients construct to send files and data over to a HTTP Server. It is commonly used by browsers and HTTP clients to upload files to the server.

To implement this request in your android applications to send images to your server follow these simple steps.

1. Add the following dependency in your build.gradle file:

                     compile 'com.squareup.okhttp3:okhttp:3.2.0'    

2. Now just add the code snippet with following parameters described as follows:


void uploadImageThroughMultipartPostRequest(File yourFileToBeUploaded) {

// yourFileToBeUploaded is your image file
        String contentType = null;
        RequestBody fileBody = null;
        if (yourFileToBeUploaded != null) {
            try {
                contentType = yourFileToBeUploaded.toURL().openConnection().getContentType();
            } catch (Exception e) {
                e.printStackTrace();
            }
            fileBody = RequestBody.create(MediaType.parse(contentType), yourFileToBeUploaded);
        }
       
       String requestURL = "YOUR_POST_REQUEST_URL" ;
       
       RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM) // Type to set Form request
                .addFormDataPart("uploaded_file", yourFileToBeUploaded.getPath())
                .addFormDataPart("uploaded_file_tag", "File_Name.jpeg", fileBody)
                .build();

        Request request = new Builder()
                .url(requestURL)
                .put(requestBody)
                .addHeader("Accept", "application/json")
                .addHeader("Content-Type", "application/json")
                .build();

        OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getActivity(), "Upload failure " + e.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                });
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                            Toast.makeText(getActivity(), "Message: "+response , Toast.LENGTH_SHORT).show();

                    }
                });
            }
        });
    }

3. Now just call the above method as follows:

            try {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            uploadImageThroughMultipartPostRequest(fileToUpload);
                        }
                    }).start();
                } catch (Exception ex) {
                    ex.getMessage();
                }

That's all.
Share and comment if any issues.


Thursday, 16 March 2017

Customizing Toast in Android

This post is regarding the customization of a Toast in your application.
You may have seen many a times some toast messages in android application notifying you that something has been completed or some action has been performed or executed.
These toast messages that you see are of the default representation from android but you can also customize your toast as you want.
This is quite simple which can be implemented as follows:

1. Create your xml layout file (custom_toast.xml) to show how your toast will look like.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="16dp"
            android:src="@drawable/sample_image" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="16dp"
            android:lines="2"
            android:text="This is your custom toast..!!!"
            android:textAlignment="center"
            android:textSize="12dp" />

    </LinearLayout>
</LinearLayout>

2. In your activity where you want to show the toast, just add the following snippet.

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.custom_toast, null);
        Toast toast = new Toast(this);
        toast.setView(layout);
        toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
        toast.show();

That's all. Here you go.
Share and comment if any issues.



Sunday, 5 March 2017

Android: Decoding a Base64 encoded string

Sometimes in your application you contain some data which is very useful to you or its so sensitive that you don't want anyone else to have it. In that you need to encode or encrypt your data while transferring it through your application.
So for encoding your data and use it in your android application, we have android.util.Base64 class which is used to encode/decode your data.
First of all encoding is not the same thing as encryption. If you’re storing or using useful and sensitive information, you should be encrypting, not simply Base64 encoding. But android.util.Base64 class is also a very useful tool for this purpose.
The use of this class is very simple as depicted in the below example:

1. First import the required class:

                         import android.util.Base64;

2. Now just use the below code: 

String str = "Hello, world!";
       
byte[] encodedStr = Base64.encode(str.getBytes(), Base64.DEFAULT);    
byte[] decodedStr = Base64.decode(encodedStr, Base64.DEFAULT);
       
Log.d("Android Castle", "Android Castle Default Value =  " + str);
Log.d("Android Castle", "Android Castle Encoded Value =  " + new String(encodedStr));
Log.d("Android Castle", "Android Castle Decoded Value =  " + new String(decodedStr));


3. The following will be out put of the above snippet:

Android Castle Default Value = Hello, world!
Android Castle Encoded Value  = SGVsbG8sIHdvcmxkIQ==
Android Castle Decoded Value = Hello, world!

But in many case we have some highly secure data where the data is encoded and then compressed and then its being transferred to your application. In that case being a developer you have to decode the data and decompress it as well to make it useful for your application. The solution for this problem is as follows:

1. Import as follows:

                    import  org.java_websocket.util.Base64;

2. Use the following code snippet:

            String st = "YOUR ENCODE STRING";

            byte[] decodedByte = new byte[0];
            byte[] result = new byte[0];
            int resultLength = 0;
            try {
                decodedByte = Base64.decode(st, Base64.GZIP);
                Inflater decompresser = new Inflater();
                decompresser.setInput(decodedByte, 0, decodedByte.length);
                result = new byte[decodedByte.length];
                resultLength = decompresser.inflate(result);
                decompresser.end();
                String outputString = new String(result, 0, resultLength, "UTF-8");
               
                System.out.println("Your decode string: " + outputString);

            } catch (Exception e) {
                e.printStackTrace();
            }

That's all.

Share and comment if any issues.




Monday, 20 February 2017

Android ViewPager with page animation

In reference to my last post here, this post will show how to implement animation in your viewPager while sliding your pages in a very simple way with a few steps as follows:

1. Add a class that contains the page transformation code as follows:
In this class, the page slide animation is ZoomOutPage transformation which means that your new page will zoom out while you slide it to either side. You will be able to understand it more clearly once you implement it. So now add a class as follows:

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
        private static final float MIN_SCALE = 0.85f;
        private static final float MIN_ALPHA = 0.5f;

        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();
            int pageHeight = view.getHeight();

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 1) { // [-1,1]
                // Modify the default slide transition to shrink the page as well
                float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
                float vertMargin = pageHeight * (1 - scaleFactor) / 2;
                float horzMargin = pageWidth * (1 - scaleFactor) / 2;
                if (position < 0) {
                    view.setTranslationX(horzMargin - vertMargin / 2);
                } else {
                    view.setTranslationX(-horzMargin + vertMargin / 2);
                }

                // Scale the page down (between MIN_SCALE and 1)
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);

                // Fade the page relative to its size.
                view.setAlpha(MIN_ALPHA +
                        (scaleFactor - MIN_SCALE) /
                                (1 - MIN_SCALE) * (1 - MIN_ALPHA));

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }


2. Add another class that implements another page slide animation:
In this class, the page slide animation is ZoomInPage transformation which means that your new page will zoom in while you slide it to either side. First let's implement it and then see the changes.

    public class ZoomInPageTransformer implements ViewPager.PageTransformer {
        private static final float MIN_SCALE = 0.75f;

        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 0) { // [-1,0]
                // Use the default slide transition when moving to the left page
                view.setAlpha(1);
                view.setTranslationX(0);
                view.setScaleX(1);
                view.setScaleY(1);

            } else if (position <= 1) { // (0,1]
                // Fade the page out.
                view.setAlpha(1 - position);

                // Counteract the default slide transition
                view.setTranslationX(pageWidth * -position);

                // Scale the page down (between MIN_SCALE and 1)
                float scaleFactor = MIN_SCALE
                        + (1 - MIN_SCALE) * (1 - Math.abs(position));
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

3. Now just after the implementation of your viewPager in your class as stated in my previous post here, add the following line:

mPager = (ViewPager) findViewById(R.id.pager);
.......             ..............
mPager.setPageTransformer(true, new ZoomOutPageTransformer());
or
mPager.setPageTransformer(true, new ZoomInPageTransformer());

That's all. Now run your code and see how it works.

Comment if any issues.