Contact list & Email support

Supplementary MyRent lab to demonstrate how to request permissions at run time. We restrict ourselves to the single permission READ_CONTACTS. We consider two scenarios: activity-fragment and viewpager-fragment.

Gradle

Add the following dependency to build.gradle (Modlule: app):

      compile "com.android.support:support-v13:23.4.0"

The FragmentCompat class, which we shall be using shortly, requires this library.

Your complete gradle file might look something like this (with the appropriate applicationId):


apply plugin: 'com.android.application'

android {
  compileSdkVersion 23
  buildToolsVersion "23.0.3"

  defaultConfig {
    applicationId "org.wit.myrent"
    minSdkVersion 19
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
  }
  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  testCompile 'junit:junit:4.12'
  compile 'com.android.support:appcompat-v7:23.4.0'
  compile "com.android.support:support-v13:23.4.0"
}

ResidenceFragment code

This code will work for both the ViewPager-Fragment and Activity-Fragment situations.

Introduce a new field for the intent data.

// This field is initialized in `onActivityResult`.
Intent data:

This field is required to provide us with access to the data intent outside the method onActivityResult.


  @Override
  public void onClick(View v)
  {
    switch (v.getId())
    {
     ...
     ...

      case R.id.tenant :
        Intent i = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
        startActivityForResult(i, REQUEST_CONTACT);
        break;

      case R.id.residence_reportButton :
        if(emailAddress == null) emailAddress = ""; // guard against null pointer
        sendEmail(getActivity(), emailAddress, getString(R.string.residence_report_subject), residence.getResidenceReport(getActivity()));
        break;

    }
  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data)
  {
    switch (requestCode) {
      case REQUEST_CONTACT:
        this.data = data;
        checkContactsReadPermission();
        break;
    }
  }

  private void readContact() {
    String name = ContactHelper.getContact(getActivity(), data);
    emailAddress = ContactHelper.getEmail(getActivity(), data);
    tenantButton.setText(name + " : " + emailAddress);
    residence.tenant = name;
  }
`
  /**
   * http://stackoverflow.com/questions/32714787/android-m-permissions-onrequestpermissionsresult-not-being-called
   * This is an override of FragmentCompat.onRequestPermissionsResult
   *
   * @param requestCode Example REQUEST_CONTACT
   * @param permissions String array of permissions requested.
   * @param grantResults int array of results for permissions request.
   */
  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
      case REQUEST_CONTACT: {
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

          readContact();
        }
        break;
      }
    }
  }

  /**
   * Bespoke method to check if read contacts permission exists.
   * If it exists then the contact sought is read.
   * Otherwise, the method FragmentCompat.request permissions is invoked and
   * The response is via the callback onRequestPermissionsResult.
   * In onRequestPermissionsResult, on successfully being granted permission then the sought contact is read.
   */
  private void checkContactsReadPermission() {
    if (ContextCompat.checkSelfPermission(getActivity(),
        Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {

      readContact();
    }
    else {
      // Invoke callback to request user-granted permission
      FragmentCompat.requestPermissions(
          this,
          new String[]{Manifest.permission.READ_CONTACTS},
          REQUEST_CONTACT);
    }
  }

These import statements are required:

import android.support.v13.app.FragmentCompat;
import android.support.v4.content.ContextCompat;
import android.Manifest;
import android.content.pm.PackageManager;

Replace the existing Fragment import with the following:

import android.app.Fragment;

Activity-Fragment

Activity class: example ResidenceActivity.

Replace:


import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;

with:

import android.app.Fragment;
import android.app.FragmentManager;

Replace:

        FragmentManager manager = getSupportFragmentManager();

with:

        FragmentManager manager = getFragmentManager();

ViewPager-Fragment

ViewPager class: example ResidencePagerActivity

Replace:


import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

with:

import android.app.Fragment;
import android.app.FragmentManager;
import android.support.v13.app.FragmentStatePagerAdapter;

Replace:

            pagerAdapter = new PagerAdapter(getSupportFragmentManager(), residences);

with:

            pagerAdapter = new PagerAdapter(getFragmentManager(), residences);