Facebook Email not found via Graph API

While providing Login with facebook option we came across the Graph API. Development goes well with SDK integration and further coding part. But problem arises when we start to realize that we are not getting the Email id of some users. which is either null or empty string.

So basically there are two main reasons why this happens.
1) If the user has an unconfirmed email in Facebook (i.e. Facebook sent him a validation mail to the user's email address but he didn't respond) Facebook WILL NOT pass that email to your app even if he gave you the email permissions.


So what we can do is use his or her Facebook email if the user has a user name (i.e. userName@facebook.com).

2) Another reason is if the user declines the Permission to an email at the state of accepting permissions from app then it would return with Empty string.
for this we have to simply check the declined permissions on the AccessToken object response.
accessToken.getDeclinedPermissions().contains("email")
Here is the full implementation of the code.

private void performFblogin() {


        AccessToken accessToken = AccessToken.getCurrentAccessToken();

        if (accessToken == null) {

                /*
                *  
                *  set permissions
                *  
                * */

            fbLoginButton.setReadPermissions(Arrays.asList("email", "user_friends", "user_birthday", "user_work_history", "user_education_history"));  // location and hometown

            callbackManager = CallbackManager.Factory.create();

            fbLoginButton.performClick();

            // Callback registration
            fbLoginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
                @Override
                public void onSuccess(LoginResult loginResult) {

                    AccessToken accessToken = loginResult.getAccessToken();

                    Log.i("accessToken", accessToken.toString());

                    if (accessToken.getDeclinedPermissions().contains("email")) {
                        //user has not granted permission for email

                        // Toast.makeText(mCon,"Email not found",Toast.LENGTH_SHORT).show();

                    
                        showEmailNotFoundDialog();
                    } else {

                        GraphRequest request = GraphRequest.newMeRequest(
                                loginResult.getAccessToken(),
                                new GraphRequest.GraphJSONObjectCallback() {
                                    @Override
                                    public void onCompleted(
                                            JSONObject object,
                                            GraphResponse response) {


                                        processResponse(object);


                                        Log.v("LoginActivity", response.toString());
                                    }


                                });

                        Bundle parameters = new Bundle();

                        parameters.putString("fields", "id,name,birthday,email,gender,link,work,education,friends{first_name,last_name}");
                        request.setParameters(parameters);
                        request.executeAsync();
                    }
                }

                @Override
                public void onCancel() {
                    Toast.makeText(mCon, "Cancelled!", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onError(FacebookException exception) {
                    Toast.makeText(mCon, "Failed", Toast.LENGTH_SHORT).show();
                }
            });
        } else {
            LoginManager.getInstance().logOut();
            performFblogin();
        }

    }

Android Timer and TimerTask scheduling

All you need to do is write a function which will schedule the timerTask and call it in the onCreate().
then manage the activity life cycle with the timer task.

public void callAsynchronousTask() {

        final Handler handler = new Handler();
        timer = new Timer();
        doAsynchronousTask = new TimerTask() {
            @Override            public void run() {
                handler.post(new Runnable() {
                    public void run() {
                        try {


                            TaskFinder tf = new TaskFinder(MainActivity.this);
                            tf.execute();
                            isTimerRunning=true;

                        } catch (Exception e) {
                            // TODO Auto-generated catch block                        }
                    }
                });
            }
        };
        timer.schedule(doAsynchronousTask, 0, 30000); //execute in every 30 sec    }
Call this function from the onCreate()

protected void onCreate(Bundle savedInstanceState) {
    // requestWindowFeature(Window.FEATURE_ACTION_BAR);    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ...
    ...
    callAsynchronousTask();
}
here is how you manage the onStop() and onRestart() of the activity.

@Overrideprotected void onStop() {
    //thread stop here
    if (timer != null) {
        timer.cancel();
        timer = null;
    }
    super.onStop();

}

@Overrideprotected void onRestart() {
    callAsynchronousTask();
    super.onRestart();

}

Recyclerview With Multiple view types

Ever wondered how to implement the multiple view types in recycler view?



Method invocation in Recyclerview:

1. Constuctor method
2. getItemViewType()
3. onCreateViewHolder()
4. onBindViewHolder()

to achieve the tast all we need to de is implement the  getItemViewType(), And it will take care of the  viewTyp parameter in   onCreateViewHolder().

/**
 * Created by Nilesh Deokar on 26/08/15.
 */
public class MyHoodAdapter extends RecyclerView.Adapter {


    LayoutInflater inflater;
    List data = Collections.emptyList();
    Context mCOn;
    Calendar calendar;

    private static final int TYPE_CRAVING = 1;
    private static final int TYPE_SHARED_DISH = 3;
    private static final int TYPE_ONLY_SHARE_DIHS = 7;

    public MyHoodAdapter(Context context, List list, int userId, String userName, int b_id) {
        this.mCOn = context;
        inflater = LayoutInflater.from(context);
        this.data = list;
        this.userId = userId;
        this.userName = userName;
        this.b_id = b_id;

    }


    @Override
    public int getItemViewType(int position) {

        return model.getStrType();

    }

    @Override
    public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        switch (viewType) {
            case TYPE_SHARED_DISH:
                return new SharedDishViewHolder(LayoutInflater.from(mCOn).inflate(R.layout.myhood_custom_row_dish, parent, false));
            case TYPE_ONLY_SHARE_DIHS:
                return new OnlySharedDishViewHolder(LayoutInflater.from(mCOn).inflate(R.layout.nearby_custom_row_shared, parent, false));
            case TYPE_CRAVING:
                return new MyViewHolder(LayoutInflater.from(mCOn).inflate(R.layout.myhood_custom_row_craving, parent, false));
         
        }
        return null;


    }

    @Override
    public void onBindViewHolder(MainViewHolder holder, int position) {

        if (holder.getItemViewType() == TYPE_SHARED_DISH) {
            SharedDishViewHolder mholder = (SharedDishViewHolder) holder;
            MyHoodModel model = data.get(position);

           /*
            * set the values to the view from your model object
            */

          } else if(holder.getItemViewType() == TYPE_ONLY_SHARE_DIHS){
            OnlySharedDishViewHolder mholder = (OnlySharedDishViewHolder) holder;
            MyHoodModel mo = data.get(position);

          }else if(holder.getItemViewType() == TYPE_CRAVING){
            MyViewHolder mHolder = (MyViewHolder) holder;
            MyHoodModel model = data.get(position);

        }
      }

    }


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




    public class MyViewHolder extends MainViewHolder {
     
    public MyViewHolder(View itemView) {
            super(itemView);
            /* Bind your object here */
         }
    }

    public class SharedDishViewHolder extends MainViewHolder {

    public SharedDishViewHolder(View itemView) {
            super(itemView);
            /* Bind your object here */
         }
    }


    public class OnlySharedDishViewHolder extends MainViewHolder {

    public OnlySharedDishViewHolder(View itemView) {
            super(itemView);
            /* Bind your object here */
         }
    }

  public class MainViewHolder extends RecyclerView.ViewHolder {
        public MainViewHolder(View v) {
            super(v);
        }
    }
}


How to resolve Glide setTag() issue

The setTag() is common method for storing data for temporary purpose and utilize it later on.
but if you are using Glide lib for image processing purpose then you might not able to use the setTag() function.

This is the stack trace..

 java.lang.IllegalArgumentException: You must not call setTag() on a view Glide is targeting
            at com.bumptech.glide.request.target.ViewTarget.getRequest(ViewTarget.java:105)
            at com.bumptech.glide.GenericRequestBuilder.into(GenericRequestBuilder.java:605)
            at net.twisterrob.app.android.view.Adapter.bindView()
            ...


This is the common use case of the Glide..
    Glide.with(mCon).load(model.getStrImagePath()).
                        placeholder(R.drawable.loading).
                        error(R.drawable.dish_placeholder)
                        .fitCenter()
                        .into(mholder.ivDishImg);

Problem arises when u write..
    mholder.ivDishImg.setTag(position);

we can use  setTag(ViewTarget,data) a constant id and data while adding tag to the ViewTarget.
and retrive the same by using getTag(ViewTarget)

ImageView ivDishImg = (ImageView) itemView.findViewById(R.id.ivMyHoodDish);
             
mholder.ivDishImg.setTag(R.id.ivMyHoodDish,position);
mHolder.ivDishImg.setOnClickListener(this);

  public void onClick(View v) {
        int position = 0;
   
        try {
            position = (Integer) v.getTag(R.id.ivMyHoodDish);
        } catch (Exception e) {
            e.printStackTrace();
       }
}








How to Implement the new Permission model in Android Marshmallow

Android has revised the permission model in the upcoming release i.e. Android M.
If we target the app for the Android M then we will have to follow the new Permission Model.

Enabling the new permissions model

To enable the new M Developer Preview permissions model, set the app's targetSdkVersion attribute to"MNC", and compileSdkVersion to "android-MNC". Doing so enables all the new permissions features.

For the preview release, you must set minSdkVersion to "MNC" to compile with the preview SDK.


Request permissions if necessary

If the app doesn't already have the permission it needs, the app calls the requestPermissions() method to request the appropriate permission or permissions. The app passes the permission or permissions it wants, and also an integer "request code". This method functions asynchronously: it returns right away, and after the user responds to the dialog box, the system calls the app's callback method with the results, passing the same "request code" that the app passed to requestPermissions().

The following code checks if the app has permission to read the user's contacts, and requests the permission if necessary:

if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (shouldShowRequestPermissionRationale(
            Manifest.permission.READ_CONTACTS)) {
        // Explain to the user why we need to read the contacts
    }

    requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
    // app-defined int constant

    return;

Handle the permissions request response


When an app requests permissions, the system presents a dialog box to the user. When the user responds, the system invokes your app's onRequestPermissionsResult(int, String[], int[]) passing it the user response. Your app needs to override that method. The callback is passed the same request code you passed to requestPermissions(). For example, if an app requests READ_CONTACTS access it might have the following callback method:

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! do the
                // calendar task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'switch' lines to check for other
        // permissions this app might request
    }
}
If the user denies a permission request, your app should take appropriate action. For example, your app might show a dialog explaining why it could not perform the user's original request.

When the system asks the user to grant a permission, the user has the option of telling the system not to ask for that permission again. In that case, when an app uses requestPermissions() to ask for that permission, the system immediately denies the request. In this case, the system calls your onRequestPermissionsResult() the same way it would if the user had explicitly rejected your request again. For this reason, your app cannot assume that any direct interaction with the user has taken place.