2017-01-25 2 views
4

J'essaye d'implémenter AutoCompleteTextView pour remplir l'email d'utilisateurs dans une activité de connexion pour un meilleur UX.Android AutoCompleteTextView avec l'email ne peuplent pas

Pour se conformer à la spécification de Google pour lire les contacts, cette application demande la permission de l'utilisateur au moment de l'exécution en utilisant la méthode checkSelfPermission() et que je sais que cela fonctionne. Cependant, lorsqu'un utilisateur tape son adresse e-mail, une liste déroulante doit apparaître après la saisie d'au moins deux caractères, ce qui n'est pas le cas.

Résultats escomptés:

enter image description here

Voici ma mise en œuvre (tentative). Toute réaction avec un exemple de code (correction) sera grandement appréciée.

build.gradle:

... 
compileSdkVersion 25 
buildToolsVersion "25.0.2" 
... 

AndroidManifest.xml:

... 
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> 
<uses-permission android:name="android.permission.READ_CONTACTS" /> 
<uses-permission android:name="android.permission.READ_PROFILE" /> 
... 

activity_login.xml:

... 
<android.support.design.widget.TextInputLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

    <AutoCompleteTextView 
     android:id="@+id/email" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:hint="@string/email" 
     android:inputType="textEmailAddress" 
     android:maxLines="1" 
     android:textColor="@android:color/white" 
     /> 

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

LoginActivity.java: (Désolé pour montrer toute la classe, mais .... juste en cas.)

package com.company.product.activity; 

import too.many.imports 

import com.company.product.R; 

import static android.Manifest.permission.READ_CONTACTS; 


public class LoginActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> { 

    // UI references. 
    private EditText inputPassword; 
    private AutoCompleteTextView inputEmail; 
    private FirebaseAuth auth; 
    private ProgressBar progressBar; 
    private Button btnSignup, btnLogin, btnReset; 

    /** 
    * Id to identity READ_CONTACTS permission request. 
    */ 
    private static final int REQUEST_READ_CONTACTS = 0; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     // Get Firebase auth instance 
     auth = FirebaseAuth.getInstance(); 

     if (auth.getCurrentUser() != null) { 
      startActivity(new Intent(LoginActivity.this, MainActivity.class)); 
      finish(); 
     } 

     // set the content view 
     setContentView(R.layout.activity_login); 

     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 

     inputEmail = (AutoCompleteTextView) findViewById(R.id.email); 
     inputPassword = (EditText) findViewById(R.id.password); 
     progressBar = (ProgressBar) findViewById(R.id.progressBar); 
     btnSignup = (Button) findViewById(R.id.btn_signup); 
     btnLogin = (Button) findViewById(R.id.btn_login); 
     btnReset = (Button) findViewById(R.id.btn_reset_password); 

     populateAutoComplete(); 

     //Get Firebase auth instance 
     auth = FirebaseAuth.getInstance(); 

     btnSignup.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       startActivity(new Intent(LoginActivity.this, SignupActivity.class)); 
      } 
     }); 

     btnReset.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       startActivity(new Intent(LoginActivity.this, ResetPasswordActivity.class)); 
      } 
     }); 

     btnLogin.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       String email = inputEmail.getText().toString(); 
       final String password = inputPassword.getText().toString(); 

       if (TextUtils.isEmpty(email)) { 
        Toast.makeText(getApplicationContext(), "Enter email address!", Toast.LENGTH_SHORT).show(); 
        return; 
       } 

       if (TextUtils.isEmpty(password)) { 
        Toast.makeText(getApplicationContext(), "Enter password!", Toast.LENGTH_SHORT).show(); 
        return; 
       } 

       progressBar.setVisibility(View.VISIBLE); 

       //authenticate user 
       auth.signInWithEmailAndPassword(email, password) 
        .addOnCompleteListener(LoginActivity.this, new OnCompleteListener<AuthResult>() 
        { 
         @Override 
         public void onComplete(@NonNull Task<AuthResult> task) { 
          // If sign in fails, display a message to the user. If sign in succeeds 
          // the auth state listener will be notified and logic to handle the 
          // signed in user can be handled in the listener. 
          progressBar.setVisibility(View.GONE); 
          if (!task.isSuccessful()) 
          { 
           // there was an error 
           if (password.length() < 6) 
           { 
            inputPassword.setError(getString(R.string.minimum_password)); 
           } 
           else 
           { 
            Toast.makeText(LoginActivity.this, getString(R.string.auth_failed), Toast.LENGTH_LONG).show(); 
           } 
          } 
          else 
          { 
           // Send to check if the user has been verified. 
           checkIfEmailVerified(); 
          } 
         } 

         // Logic for checking if the email is verified or not 
         private void checkIfEmailVerified() 
         { 
          FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); 
          if (user.isEmailVerified()) 
          { 
           // user is verified, finish this activity and send to MainActivity. 
           Toast.makeText(LoginActivity.this, "Successfully logged in: Lets start flying!", Toast.LENGTH_SHORT).show(); 
           Intent intent = new Intent(LoginActivity.this, MainActivity.class); 
           startActivity(intent); 
           finish(); 
          } 
          else 
          { 
           // Email is not verified and prompt a message to the user and restart this activity. 
           // NOTE: don't forget to log out the user. 
           FirebaseAuth.getInstance().signOut(); 
          } 
         } 

        }); 
      } 
     }); 
    } 

    private void populateAutoComplete() { 
     if (!mayRequestContacts()) { 
      return; 
     } 

     getSupportLoaderManager().initLoader(0, null, this); 
    } 

    private boolean mayRequestContacts() { 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 
      return true; 
     } 
     if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) { 
      return true; 
     } 
     if (shouldShowRequestPermissionRationale(READ_CONTACTS)) { 
      Snackbar.make(inputEmail, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE) 
        .setAction(android.R.string.ok, new View.OnClickListener() { 
         @Override 
         @TargetApi(Build.VERSION_CODES.M) 
         public void onClick(View v) { 
          requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS); 
         } 
        }); 
     } else { 
      requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS); 
     } 
     return false; 
    } 

    /** 
    * Callback received when a permissions request has been completed. 
    */ 
    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 
              @NonNull int[] grantResults) { 
     if (requestCode == REQUEST_READ_CONTACTS) { 
      if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       populateAutoComplete(); 
      } 
     } 
    } 

    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) { 
     return new CursorLoader(this, 
       // Retrieve data rows for the device user's 'profile' contact. 
       Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI, 
         ContactsContract.Contacts.Data.CONTENT_DIRECTORY), ProfileQuery.PROJECTION, 

       // Select only email addresses. 
       ContactsContract.Contacts.Data.MIMETYPE + 
         " = ?", new String[]{ContactsContract.CommonDataKinds.Email 
       .CONTENT_ITEM_TYPE}, 

       // Show primary email addresses first. Note that there won't be 
       // a primary email address if the user hasn't specified one. 
       ContactsContract.Contacts.Data.IS_PRIMARY + " DESC"); 
    } 

    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { 
     List<String> emails = new ArrayList<>(); 
     cursor.moveToFirst(); 
     while (!cursor.isAfterLast()) { 
      emails.add(cursor.getString(ProfileQuery.ADDRESS)); 
      cursor.moveToNext(); 
     } 

     addEmailsToAutoComplete(emails); 
    } 

    public void onLoaderReset(Loader<Cursor> cursorLoader) { 

    } 

    private void addEmailsToAutoComplete(List<String> emailAddressCollection) { 
     //Create adapter to tell the AutoCompleteTextView what to show in its dropdown list. 
     ArrayAdapter<String> adapter = 
       new ArrayAdapter<>(LoginActivity.this, 
         android.R.layout.simple_dropdown_item_1line, emailAddressCollection); 

     inputEmail.setAdapter(adapter); 
    } 


    private interface ProfileQuery { 
     String[] PROJECTION = { 
       ContactsContract.CommonDataKinds.Email.ADDRESS, 
       ContactsContract.CommonDataKinds.Email.IS_PRIMARY, 
     }; 

     int ADDRESS = 0; 
     int IS_PRIMARY = 1; 
    } 

} 
+0

Etes-vous sûr d'obtenir des résultats dans 'onLoadFinished()'? Je ne peux pas dire que j'ai déjà beaucoup utilisé le fournisseur de contacts, mais les données de requête que vous créez avec 'CursorLoader' ne semblent pas tout à fait correctes. –

+0

sont capables d'obtenir tous les contact e-mail? –

Répondre

0

Vous pouvez y parvenir comme suit:

  1. d'abord créer une coutume ArrayAdapter au lieu de

    ArrayAdapter<String> adapter = 
         new ArrayAdapter<>(LoginActivity.this, 
           android.R.layout.simple_dropdown_item_1line, emailAddressCollection); 
    
    inputEmail.setAdapter(adapter); 
    
  2. Supposons que nous l'appelons AutoCompleteAdapter et laissez-il mettre en œuvre l'interface Filterable

    public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable { 
    
  3. Remplacer les getFilter() et mettre le contrôle de longueur char à 2 caractères pour le courrier électronique.

1

Vous pouvez le faire

rendre votre adaptateur comme variable globale et ajouter textwatcher pour le courrier électronique d'entrée et définissez votre carte que lorsque la taille du texte atteint 2

inputEmail.addTextChangedListener(new TextWatcher() { 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 

      if (s.length() < 2) { 

      inputEmail.setAdapter(null) 

      } 
      else if(s.length()==2){ 
        //this is to make sure adapter not getting set every time if length is greater than 2 
      inputEmail.setAdapter(adapter) 

      } 
     } 

     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 


     } 

     @Override 
     public void afterTextChanged(Editable s) { 


     } 
    }); 

changer la condition que vous prefer.Hope this helps

8

Remplacez votre code de méthode onCreateLoader() par le code ci-dessous.

public Loader<Cursor> onCreateLoader(int i, Bundle bundle) { 
    return new CursorLoader(this, 
      // Retrieve data rows for the device user's 'profile' contact. 
      ContactsContract.Data.CONTENT_URI, ProfileQuery.PROJECTION, 

      // Select only email addresses. 
      ContactsContract.Contacts.Data.MIMETYPE + 
        " = ?", new String[]{ContactsContract.CommonDataKinds.Email 
      .CONTENT_ITEM_TYPE}, 

      // Show primary email addresses first. Note that there won't be 
      // a primary email address if the user hasn't specified one. 
      ContactsContract.Contacts.Data.IS_PRIMARY + " DESC"); 
} 
+0

Ceci est la bonne réponse, devrait être acceptée. – KunalK

+0

Thnx !. Désolé de revenir à ça jusqu'à la dernière minute. Maintenant je dois me débrouiller pour sortir de cette activité afin de pouvoir la réutiliser dans d'autres - LOL. – CelticParser