Tuesday 24 January 2017

Android RecycleView Example Using MySQL and include SearchView

Here is simple tutorial of android recycleview cardview example using PHP MySQL and also provided search view filtering.



Gradle

compile 'com.loopj.android:android-async-http:1.4.5'
compile 'com.android.support:design:24.2.1'
compile 'com.github.bumptech.glide:glide:3.5.2'
compile 'com.android.support:support-v4:24.2.1'
compile 'com.android.support:recyclerview-v7:+'
compile 'com.android.support:cardview-v7:+'
 compile files("${android.getSdkDirectory().getAbsolutePath()}" + File.separator + "platforms" + File.separator + "android-23" + File.separator + "optional" + File.separator + "org.apache.http.legacy.jar")

MainActivity.java

package com.recyclerviewexample;

import android.content.Intent;
import android.os.AsyncTask;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Filter;
import static java.security.AccessController.getContext;

public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
    private static final String TAG = "RecyclerViewExample";
    private List<FeedItem> feedsList;
    private RecyclerView mRecyclerView;
    private MyRecyclerViewAdapter adapter;
    private ProgressBar progressBar;

    private SearchView mSearchView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        String url = "http://krishscs.esy.es/RecycleViewExample/RecycleViewExample.php";
        mSearchView = (SearchView) findViewById(R.id.search_view);
        setupSearchView();
        new DownloadTask().execute(url);
}
   public class DownloadTask extends AsyncTask<String, Void, Integer> {
        @Override
        protected void onPreExecute() {
            progressBar.setVisibility(View.VISIBLE);
        }
@Override
        protected Integer doInBackground(String... params) {
            Integer result = 0;
            HttpURLConnection urlConnection;
            try {
                URL url = new URL(params[0]);
                urlConnection = (HttpURLConnection) url.openConnection();
                int statusCode = urlConnection.getResponseCode();

                // 200 represents HTTP OK
                if (statusCode == 200) {
                    BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = r.readLine()) != null) {
                        response.append(line);
                    }
                    parseResult(response.toString());
                    result = 1; // Successful
                } else {
                    result = 0; //"Failed to fetch data!";
                }
            } catch (Exception e) {
                Log.d(TAG, e.getLocalizedMessage());
            }
            return result; //"Failed to fetch data!";
        }

        @Override
        protected void onPostExecute(Integer result) {
            progressBar.setVisibility(View.GONE);

            if (result == 1) {
                adapter = new MyRecyclerViewAdapter(MainActivity.this, feedsList);
                mRecyclerView.setAdapter(adapter);
            } else {
                Toast.makeText(MainActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void parseResult(String result) {
        try {
            feedsList = new ArrayList<FeedItem>();
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("result");
            for (int i = 0; i < posts.length(); i++) {
                JSONObject post = posts.optJSONObject(i);
                FeedItem item = new FeedItem();
                item.setTitle(post.optString("name"));
                item.setThumbnail(post.optString("image"));
                feedsList.add(item);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    private void setupSearchView() {
        // mSearchView.setIconifiedByDefault(false);
        mSearchView.setOnQueryTextListener(this);
//        adapter.setFilter(feedsList);
        // mSearchView.setSubmitButtonEnabled(true);
        mSearchView.setQueryHint("Search here....");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.searchview_in_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Take appropriate action for each action item click
int id = item.getItemId();
        if (id == R.id.search) {
            // Handle the camera action
            final SearchView searchView = (SearchView)  MenuItemCompat.getActionView(item);
            searchView.setOnQueryTextListener(this);
        }
        return true;
    }
    @Override
    public boolean onQueryTextChange(String newText) {
        final List<FeedItem> filteredModelList = filter(feedsList, newText);
        adapter.setFilter(filteredModelList);
        return true;
    }
    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }
    private List<FeedItem> filter(List<FeedItem> models, String query) {
        query = query.toLowerCase();final List<FeedItem> filteredModelList = new ArrayList<>();
        for (FeedItem model : models) {
            final String name = model.getTitle().toLowerCase();
            if (name.contains(query)) {
                filteredModelList.add(model);
            }
        }
        return filteredModelList;
    }
}


MyRecyclerViewAdapter.java

package com.recyclerviewexample;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import java.util.ArrayList;
import java.util.List;

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.CustomViewHolder> {
    private List<FeedItem> feedItemList;
    private Context mContext;
    //private OnItemClickListener onItemClickListener;
    View view;
    public MyRecyclerViewAdapter(Context context, List<FeedItem> feedItemList) {
        this.feedItemList = feedItemList;
        this.mContext = context;
        //this.feedItemList = new ArrayList<FeedItem>();
        // we copy the original list to the filter list and use it for setting row values
        //this.feedItemList.addAll(this.feedItemList);
    }
    @Override
    public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null);
        CustomViewHolder viewHolder = new CustomViewHolder(view);
        return viewHolder;
    }
    @Override
    public void onBindViewHolder(CustomViewHolder customViewHolder, int i) {
        final FeedItem feedItem = feedItemList.get(i);
        //Download image using picasso library
        if (!TextUtils.isEmpty(feedItem.getThumbnail())) {
            Glide.with(mContext).load(feedItem.getThumbnail()).diskCacheStrategy(DiskCacheStrategy.ALL)
                    .into(customViewHolder.imageView);
        }

        //Setting text view title
        customViewHolder.textView.setText(Html.fromHtml(feedItem.getTitle()));
        customViewHolder.textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(view.getContext(), feedItem.getTitle(), Toast.LENGTH_SHORT).show();            }
        });
      /*  final View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //onItemClickListener.onItemClick(feedItem);
                Toast.makeText(view.getContext(),feedItem.getTitle(), Toast.LENGTH_SHORT).show();
            }
        };*/
        /*customViewHolder.imageView.setOnClickListener(listener);
        customViewHolder.textView.setOnClickListener(listener);*/
    }
    class CustomViewHolder extends RecyclerView.ViewHolder {
        protected ImageView imageView;
        protected TextView textView;

        public CustomViewHolder(View view) {
            super(view);
            this.imageView = (ImageView) view.findViewById(R.id.thumbnail);
            this.textView = (TextView) view.findViewById(R.id.title);
        }
    }


    @Override
    public int getItemCount() {
        return feedItemList.size();
    }

    public void setFilter(List<FeedItem> countryModels) {
        feedItemList = new ArrayList<>();
        feedItemList.addAll(countryModels);
        notifyDataSetChanged();
    }
}

FeedItem.java

package com.recyclerviewexample;
public class FeedItem {
    private String title;
    private String thumbnail;
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getThumbnail() {
        return thumbnail;
    }
    public void setThumbnail(String thumbnail) {
        this.thumbnail = thumbnail;
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.recyclerviewexample">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f1f1f1"
    android:padding="12dp"
    tools:context=".MainActivity">
    <android.support.v7.widget.SearchView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/search_view"
        android:focusable="false"
        android:focusableInTouchMode="false">
    </android.support.v7.widget.SearchView>
    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/search_view" />

</RelativeLayout>

searchview_in_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/search"
        android:icon="@android:drawable/ic_menu_search"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:title="search............."
        app:showAsAction="collapseActionView|ifRoom" />
</menu>

list_row.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:cardview="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="5dp"
    cardview:cardCornerRadius="8dp"
    cardview:cardElevation="3dp"
    cardview:cardUseCompatPadding="true">

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

        <ImageView
            android:id="@+id/thumbnail"
            android:layout_width="match_parent"
            android:layout_height="180dp"
            android:layout_alignParentTop="true"
            android:scaleType="fitXY"/>

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/thumbnail"
            android:layout_centerVertical="true"
            android:layout_marginLeft="12dp"
            android:hint="Name"
            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
            android:textColor="#444"
            android:textSize="18dp"
            android:textStyle="bold"/>


    </RelativeLayout>
</android.support.v7.widget.CardView>

PHP’s




RecycleViewExample.php

<?php
 require_once('db_Connect.php');
$sql = "select * from RecycleViewExample";
$res = mysqli_query($con,$sql);
$result = array();
while($row = mysqli_fetch_array($res)){
array_push($result,
array('id'=>$row[0],
'name'=>$row[1],
'image'=>$row[2]
));
}
echo json_encode(array("result"=>$result));
mysqli_close($con);
?>

db_Connect.php

<?php
 define('HOST','mysql.hostinger.in');
 define('USER','u293140154_user');
 define('PASS','******');
 define('DB','u293140154_test');
  $con = mysqli_connect(HOST,USER,PASS,DB) or die('Unable to Connect');
 ?>



Friday 20 January 2017

Google Plus Login Integration in Android


1.  Installing Google Play Services
Open SDK Manager and download google play services



2. Generating Google-Services.json
2.1 Find keytool can be used to generate SHA-1.
On windows = keytool -list -v -keystore "%                                        USERPROFILE%\.android\debug.keystore" -alias                                        androiddebugkey -storepass android -keypass android

2.2 click on Get A Configuration File button



              
3. Creating New Project
          3.1 Open project level build.gradle(Project: GooglePlusLogin) and add...
            dependencies{
         classpath 'com.android.tools.build:gradle:2.2.3'
        
classpath 'com.google.gms:google-services:3.0.0'
       }
3.2 Open app level build.gradle and add...
                compile 'com.google.android.gms:play-services-auth:9.2.1'
         compile 'com.github.bumptech.glide:glide:3.7.0'
3.3 Open string.xml File and put.....
                <string name="btn_logout_from_google">Logout from Google</string>
         <
string name="btn_revoke_access">Revoke Access</string>
         <
string name="loading">wait......</string>
3.4 Open Design file acrivity_main2.xml
                  <?xml version="1.0" encoding="utf-8"?>
          <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"
              
android:padding="16dp"
             
tools:context=".MainActivity" >

           <
LinearLayout
             
android:id="@+id/llProfile"
             
android:layout_width="fill_parent"
             
android:layout_height="wrap_content"
              
android:layout_marginBottom="20dp"
             
android:orientation="horizontal"
             
android:weightSum="3"
              
android:visibility="gone">

                 <
ImageView
                
android:id="@+id/imgProfilePic"
                 
android:layout_width="80dp"
                
android:layout_height="wrap_content"
                
android:layout_weight="1"/>

                 <
LinearLayout
                  
android:layout_width="wrap_content"
                  
android:layout_height="wrap_content"
                  
android:layout_marginLeft="10dp"
                  
android:orientation="vertical"
                  
android:layout_weight="2" >

                     <
TextView
                      
android:id="@+id/txtName"
                      
android:layout_width="wrap_content"
                      
android:layout_height="wrap_content"
                      
android:padding="5dp"
                      
android:textSize="20dp" />

                     <
TextView
                       
android:id="@+id/txtEmail"
                      
android:layout_width="wrap_content"
                      
android:layout_height="wrap_content"
                      
android:padding="5dp"
                      
android:textSize="18dp" />
                    </
LinearLayout>
             </
LinearLayout>

             <
com.google.android.gms.common.SignInButton
                
android:id="@+id/btn_sign_in"
                
android:layout_width="fill_parent"
                
android:layout_height="wrap_content"
                
android:layout_marginBottom="20dp"/>

             <
Button
                
android:id="@+id/btn_sign_out"
                
android:layout_width="fill_parent"
                
android:layout_height="wrap_content"
                
android:text="@string/btn_logout_from_google"
                
android:visibility="gone"
                
android:layout_marginBottom="10dp"/>

             <
Button
                
android:id="@+id/btn_revoke_access"
                
android:layout_width="fill_parent"
                
android:layout_height="wrap_content"
                
android:text="@string/btn_revoke_access"
                
android:visibility="gone" />

          </
LinearLayout>

3.5 Open Java File Main2activity.java
package com.jainish.googlepluslogin;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.OptionalPendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;

public class Main2Activity extends AppCompatActivity implements
       
View.OnClickListener,
        GoogleApiClient.OnConnectionFailedListener {

   
private static final String TAG = Main2Activity.class.getSimpleName();
   
private static final int RC_SIGN_IN = 007;

   
private GoogleApiClient mGoogleApiClient;
   
private ProgressDialog mProgressDialog;

   
private SignInButton btnSignIn;
   
private Button btnSignOut, btnRevokeAccess;
   
private LinearLayout llProfileLayout;
   
private ImageView imgProfilePic;
   
private TextView txtName, txtEmail;

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

       
btnSignIn = (SignInButton) findViewById(R.id.btn_sign_in);
       
btnSignOut = (Button) findViewById(R.id.btn_sign_out);
       
btnRevokeAccess = (Button) findViewById(R.id.btn_revoke_access);
       
llProfileLayout = (LinearLayout) findViewById(R.id.llProfile);
       
imgProfilePic = (ImageView) findViewById(R.id.imgProfilePic);
       
txtName = (TextView) findViewById(R.id.txtName);
       
txtEmail = (TextView) findViewById(R.id.txtEmail);

       
btnSignIn.setOnClickListener(this);
       
btnSignOut.setOnClickListener(this);
       
btnRevokeAccess.setOnClickListener(this);

        GoogleSignInOptions gso =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();

       
mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(
this, this)
                .addApi(Auth.
GOOGLE_SIGN_IN_API, gso)
                .build();

       
// Customizing G+ button
       
btnSignIn.setSize(SignInButton.SIZE_STANDARD);
       
btnSignIn.setScopes(gso.getScopeArray());
    }


   
private void signIn() {
        Intent signInIntent = Auth.
GoogleSignInApi.getSignInIntent(mGoogleApiClient);
        startActivityForResult(signInIntent,
RC_SIGN_IN);
    }

   
private void signOut() {
        Auth.
GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
               
new ResultCallback<Status>() {
                   
@Override
                   
public void onResult(Status status) {
                        updateUI(
false);
                    }
                });
    }

   
private void revokeAccess() {
        Auth.
GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
               
new ResultCallback<Status>() {
                   
@Override
                   
public void onResult(Status status) {
                        updateUI(
false);
                    }
                });
    }

   
private void handleSignInResult(GoogleSignInResult result) {

        Toast.makeText(getApplicationContext(),
"handleSignInResult:" + result.isSuccess(),Toast.LENGTH_LONG).show();
        Log.d(
TAG, "handleSignInResult:" + result.isSuccess());
       
if (result.isSuccess()) {
           
// Signed in successfully, show authenticated UI.
           
GoogleSignInAccount acct = result.getSignInAccount();

            Log.e(
TAG, "display name: " + acct.getDisplayName());

            String personName = acct.getDisplayName();
            String personPhotoUrl = acct.getPhotoUrl().toString();
            String email = acct.getEmail();

            Log.e(
TAG, "Name: " + personName + ", email: " + email
                    +
", Image: " + personPhotoUrl);

            
txtName.setText(personName);
           
txtEmail.setText(email);
            Glide.with(getApplicationContext()).load(personPhotoUrl)
                    .thumbnail(
0.5f)
                    .crossFade()
                    .diskCacheStrategy(DiskCacheStrategy.
ALL)
                    .into(
imgProfilePic);

            Toast.makeText(getApplicationContext(),personName,Toast.
LENGTH_LONG).show();
            updateUI(
true);
        }
else {
           
updateUI(false);
        }
    }
   
@Override
   
public void onClick(View v) {
       
int id = v.getId();

       
switch (id) {
           
case R.id.btn_sign_in:
                signIn();
               
break;

           
case R.id.btn_sign_out:
                signOut();
               
break;

           
case R.id.btn_revoke_access:
                revokeAccess();
               
break;
        }
    }
   
@Override
   
public void onActivityResult(int requestCode, int resultCode, Intent data) {
       
super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult result = Auth.
GoogleSignInApi.getSignInResultFromIntent(data);
            handleSignInResult(result);
        }
    }
   
@Override
   
public void onStart() {
       
super.onStart();

        OptionalPendingResult<GoogleSignInResult> opr = Auth.
GoogleSignInApi.silentSignIn(mGoogleApiClient);
       
if (opr.isDone()) {
          
            Log.d(TAG, "Got cached sign-in");
            GoogleSignInResult result = opr.get();
            handleSignInResult(result);
        }
else {
            showProgressDialog();
            opr.setResultCallback(
new ResultCallback<GoogleSignInResult>() {
                
@Override
               
public void onResult(GoogleSignInResult googleSignInResult) {
                    hideProgressDialog();
                    handleSignInResult(googleSignInResult);
                }
            });
        }
    }

   
@Override
   
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
  
        Log.d(TAG, "onConnectionFailed:" + connectionResult);
    }

   
private void showProgressDialog() {
       
if (mProgressDialog == null) {
           
mProgressDialog = new ProgressDialog(this);
           
mProgressDialog.setMessage(getString(R.string.loading));
           
mProgressDialog.setIndeterminate(true);
        }

       
mProgressDialog.show();
    }

   
private void hideProgressDialog() {
       
if (mProgressDialog != null && mProgressDialog.isShowing()) {
           
mProgressDialog.hide();
        }
    }

   
private void updateUI(boolean isSignedIn) {
       
if (isSignedIn) {
           
btnSignIn.setVisibility(View.GONE);
           
btnSignOut.setVisibility(View.VISIBLE);
           
btnRevokeAccess.setVisibility(View.VISIBLE);
           
llProfileLayout.setVisibility(View.VISIBLE);
        }
else {
           
btnSignIn.setVisibility(View.VISIBLE);
           
btnSignOut.setVisibility(View.GONE);
           
btnRevokeAccess.setVisibility(View.GONE);
           
llProfileLayout.setVisibility(View.GONE);
        }
    }
}

           
Output