Come ottenere l'indirizzo e-mail principale del dispositivo Android


412

Come si ottiene l'indirizzo e-mail principale di Android (o un elenco di indirizzi e-mail)?

Comprendo che su OS 2.0+ esiste il supporto per più indirizzi e-mail, ma al di sotto di 2.0 è possibile avere un solo indirizzo e-mail per dispositivo.


Stai parlando di recuperare un indirizzo email di contatti?
Austyn Mahoney,

1
No, l'indirizzo e-mail principale del dispositivo.
Brandon O'Rourke,

Esistono uno o più indirizzi e-mail associati a un dispositivo Android, giusto? Questo è quello che vorrei.
Brandon O'Rourke,

2
@ BrandonO'Rourke Intendi "l'indirizzo e-mail principale del dispositivo" come quello associato ad Android Market? Perché c'è una differenza tra l'ID gmail associato ad Android Market e altre e-mail. Dai un'occhiata a questa domanda stackoverflow.com/questions/10606976/…
Gaurav Agarwal

Risposte:


749

Esistono diversi modi per farlo, mostrato di seguito.

Come avviso amichevole, fai attenzione e in anticipo all'utente quando gestisci i dati di account, profilo e contatti. Se usi in modo improprio l'indirizzo e-mail di un utente o altre informazioni personali, possono accadere cose brutte.

Metodo A: utilizzare AccountManager (livello API 5+)

È possibile utilizzare AccountManager.getAccountso AccountManager.getAccountsByTypeper ottenere un elenco di tutti i nomi degli account sul dispositivo. Fortunatamente, per alcuni tipi di account (incluso com.google), i nomi degli account sono indirizzi e-mail. Esempio di frammento di seguito.

Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
    if (emailPattern.matcher(account.name).matches()) {
        String possibleEmail = account.name;
        ...
    }
}

Si noti che ciò richiede l' GET_ACCOUNTSautorizzazione:

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

Ulteriori informazioni sull'utilizzo AccountManagersono disponibili nel codice di esempio di Contact Manager nell'SDK.

Metodo B: utilizzare ContactsContract.Profile (livello API 14+)

A partire da Android 4.0 (Ice Cream Sandwich), puoi ottenere gli indirizzi email dell'utente accedendo al loro profilo. L'accesso al profilo utente è un po 'pesante in quanto richiede due autorizzazioni (più su quello che segue), ma gli indirizzi e-mail sono pezzi di dati abbastanza sensibili, quindi questo è il prezzo di ammissione.

Di seguito è riportato un esempio completo che utilizza a CursorLoaderper recuperare righe di dati del profilo contenenti indirizzi e-mail.

public class ExampleActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor> {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle arguments) {
        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");
    }

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

        ...
    }

    @Override
    public void onLoaderReset(Loader<Cursor> cursorLoader) {
    }

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

        int ADDRESS = 0;
        int IS_PRIMARY = 1;
    }
}

Ciò richiede sia l' READ_PROFILEe READ_CONTACTSpermesso:

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

3
ho una domanda simile usando il tuo codice sono in grado di ottenere tutti gli ID di Gmail associati al mio telefono ma voglio quello principale. Ho trovato una soluzione come quando aggiungiamo più ID di posta elettronica per la sincronizzazione con il telefono che si trova in una pila se sto ottenendo la 0a posizione com.google id, sto ricevendo quella principale perché entra per prima e acquisisce la 0a posizione in una pila . Ecco il mio codice Account [] account = AccountManager.get (questo) .getAccountsByType ("com.google"); String myEmailid = accounts [0] .toString (); Log.d ("Il mio ID e-mail che desidero", myEmailid); so che non è il modo corretto.
PiyushMishra

59
Il metodo del profilo è gravemente difettoso (secondo me). Un'app che vuole / ha bisogno della mia e-mail non è un grosso problema rispetto a un'app che vuole leggere tutti i miei contatti, ma ce l'hai fatta in modo che entrambi richiedano le stesse autorizzazioni. Quindi, come utente, non posso dire la differenza tra un'app che leggerà la mia e-mail e un'app che leggerà i miei oltre 500 contatti. Questo è un problema molto reale e pratico poiché il numero di app che abusano dei tuoi contatti sta crescendo!
Tom,

3
@Muzikant Non è affatto una dichiarazione ufficiale, ma è qualcosa che è abbastanza improbabile che cambi. Detto questo, il modo "corretto" di accedere agli indirizzi e-mail di un utente è il Metodo B. Questo è più "ufficiale" e il fatto che sia dietro alcune autorizzazioni pesanti dovrebbe indicare la sensibilità con cui dovresti avvicinarti a tali dati.
Roman Nurik,

15
Sono d'accordo con @ Tom su questo. Chiedere l'autorizzazione per i dati di tutti i contatti sul telefono solo per il nome e il cognome dell'utente è ridicolo.
tasomaniaco

3
Il metodo B non funziona per me in Android 4.4 copiando tutto il codice di esempio. cursor.isAfterLast()restituisce sempre vero. Qualche idea?
cprcrack,

55

Questo potrebbe essere utile per gli altri:

Utilizzo di AccountPicker per ottenere l'indirizzo e-mail dell'utente senza autorizzazioni globali e consentire all'utente di essere a conoscenza e autorizzare o annullare il processo.


1
Questa è una risposta molto utile, penso che questa dovrebbe essere l'opzione preferita, poiché l'email principale di solito indica l'account Google, che a sua volta avrai in combinazione con Google Play
Alex.F

@ Alex.F Funziona con le versioni Android dopo / da marshmellow?
Eswar

27

Vorrei utilizzare AccountPicker di Android , introdotto in ICS.

Intent googlePicker = AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null);
startActivityForResult(googlePicker, REQUEST_CODE);

E quindi attendere il risultato:

protected void onActivityResult(final int requestCode, final int resultCode,
                                final Intent data) {
    if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
        String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
    }
}

2
Si noti che richiede di utilizzare i servizi di gioco e che in alcuni casi mostrerà una finestra di dialogo, che l'utente dovrà scegliere l'account.
sviluppatore Android

Utilizzando AccountManager.newChooseAccountIntent () fai lo stesso lavoro e non richiede la libreria play-services.
Denis

Questo fa apparire un utente all'utente per l'autenticazione dell'account nel contesto dell'ultima versione di Android? Se sì, come posso ignorarlo per un dispositivo con un solo account?
Eswar,

14
public String getUsername() {
    AccountManager manager = AccountManager.get(this);
    Account[] accounts = manager.getAccountsByType("com.google");
    List<String> possibleEmails = new LinkedList<String>();

    for (Account account : accounts) {
        // TODO: Check possibleEmail against an email regex or treat
        // account.name as an email address only for certain account.type values.
        possibleEmails.add(account.name);
    }

    if (!possibleEmails.isEmpty() && possibleEmails.get(0) != null) {
        String email = possibleEmails.get(0);
        String[] parts = email.split("@");

        if (parts.length > 1)
            return parts[0];
    }
    return null;
}

Metodo semplice e piacevole Grazie :)
Talha Q

2
Si noti che ciò richiede android.permission.GET_ACCOUNTS, che è definito permesso "pericoloso" (richiede una richiesta di runtime): developer.android.com/reference/android/…
SagiLow

@SagiLow Come hai gestito questo? Non voglio chiedere all'utente, per un'altra autorizzazione, solo per renderlo pigro per inserire il suo indirizzo e-mail :)
basato su codice

1
@codebased Non l'ho fatto ... non è possibile per quanto ne so.
Sagi Basso

2
manager.getAccountsByType ( "com.google"); non funziona con le versioni successive di Android.
powder366

8

Esiste un'API Android che consente all'utente di selezionare il proprio indirizzo e-mail senza la necessità di un'autorizzazione. Dai un'occhiata a: https://developers.google.com/identity/smartlock-passwords/android/retrieve-hints

HintRequest hintRequest = new HintRequest.Builder()
        .setHintPickerConfig(new CredentialPickerConfig.Builder()
                .setShowCancelButton(true)
                .build())
        .setEmailAddressIdentifierSupported(true)
        .setAccountTypes(IdentityProviders.GOOGLE)
        .build();

PendingIntent intent = mCredentialsClient.getHintPickerIntent(hintRequest);
try {
    startIntentSenderForResult(intent.getIntentSender(), RC_HINT, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
    Log.e(TAG, "Could not start hint picker Intent", e);
}

Questo mostrerà un selettore in cui l'utente può selezionare un indirizzo e-mail. Il risultato verrà consegnatoonActivityResult()


Posso confermare che sono stato in grado di utilizzare questo, grazie per l'unica risposta funzionante che ho trovato
csga5000,

L'unica soluzione funzionante, grazie vorticoso
Zulqarnain

7

La risposta tristemente accettata non funziona.

Sono in ritardo, ma ecco la soluzione per l'applicazione di posta elettronica Android interna a meno che l'uri del contenuto non venga modificato dal provider:

Uri EMAIL_ACCOUNTS_DATABASE_CONTENT_URI = 
              Uri.parse("content://com.android.email.provider/account");

public ArrayList<String> GET_EMAIL_ADDRESSES ()
{
    ArrayList<String> names = new ArrayList<String>();
    ContentResolver cr      = m_context.getContentResolver();
    Cursor cursor           = cr.query(EMAIL_ACCOUNTS_DATABASE_CONTENT_URI ,null, 
                             null, null, null);

    if (cursor == null) {
        Log.e("TEST", "Cannot access email accounts database");
        return null;
    }

    if (cursor.getCount() <= 0) {
        Log.e("TEST", "No accounts");
        return null;
    }

    while (cursor.moveToNext()) {
        names.add(cursor.getString(cursor.getColumnIndex("emailAddress")));
        Log.i("TEST", cursor.getString(cursor.getColumnIndex("emailAddress")));
    }
    return names;
}


2

Usa questo metodo:

 public String getUserEmail() {
    AccountManager manager = AccountManager.get(App.getInstance());
    Account[] accounts = manager.getAccountsByType("com.google");
    List<String> possibleEmails = new LinkedList<>();
    for (Account account : accounts) {
        possibleEmails.add(account.name);
    }
    if (!possibleEmails.isEmpty() && possibleEmails.get(0) != null) {
        return possibleEmails.get(0);
    }
    return "";
}

Si noti che ciò richiede l' GET_ACCOUNTSautorizzazione:

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

Poi:

editTextEmailAddress.setText(getUserEmail());

Questo sembra restituire solo gli account associati all'app corrente - quindi ottengo "nessuno" nei test
csga5000,

manager.getAccountsByType ("com.google") non funziona nelle versioni successive di Android. E da cosa proviene App.getInstance ()?
powder366


0

Android bloccato GET_ACCOUNTS recente, quindi alcune delle risposte non hanno funzionato per me. Ho funzionato su Android 7.0 con l'avvertenza che i tuoi utenti devono sopportare una finestra di dialogo delle autorizzazioni.

AndroidManifest.xml

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

MainActivity.java

package com.example.patrick.app2;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.accounts.AccountManager;
import android.accounts.Account;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.*;

public class MainActivity extends AppCompatActivity {

    final static int requestcode = 4; //arbitrary constant less than 2^16

    private static String getEmailId(Context context) {
        AccountManager accountManager = AccountManager.get(context);
        Account[] accounts = accountManager.getAccountsByType("com.google");
        Account account;
        if (accounts.length > 0) {
            account = accounts[0];
        } else {
            return "length is zero";
        }
        return account.name;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case requestcode:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    String emailAddr = getEmailId(getApplicationContext());
                    ShowMessage(emailAddr);

                } else {
                    ShowMessage("Permission Denied");
                }
        }
    }

    public void ShowMessage(String email)
    {
        AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
        alertDialog.setTitle("Alert");
        alertDialog.setMessage(email);
        alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
        alertDialog.show();
    }

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

        Context context = getApplicationContext();

        if ( ContextCompat.checkSelfPermission( context, android.Manifest.permission.GET_ACCOUNTS )
                != PackageManager.PERMISSION_GRANTED )
        {
            ActivityCompat.requestPermissions( this, new String[]
                            {  android.Manifest.permission.GET_ACCOUNTS  },requestcode );
        }
        else
        {
            String possibleEmail = getEmailId(getApplicationContext());
            ShowMessage(possibleEmail);
        }
    }
}

Questo non differisce dalle altre risposte e sembra che quelle non funzionino per me - apparentemente perché nelle versioni più recenti di Android restituisce solo account associati all'app e non richiede più l'autorizzazione.
csga5000,

0

Funziona nel sistema operativo MarshMallow

    btn_click=(Button) findViewById(R.id.btn_click);

    btn_click.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0)
        {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            {
                int permissionCheck = ContextCompat.checkSelfPermission(PermissionActivity.this,
                        android.Manifest.permission.CAMERA);
                if (permissionCheck == PackageManager.PERMISSION_GRANTED)
                {
                    //showing dialog to select image
                    String possibleEmail=null;

                     Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
                     Account[] accounts = AccountManager.get(PermissionActivity.this).getAccounts();
                     for (Account account : accounts) {
                         if (emailPattern.matcher(account.name).matches()) {
                             possibleEmail = account.name;
                             Log.e("keshav","possibleEmail"+possibleEmail);
                         }
                     }

                    Log.e("keshav","possibleEmail gjhh->"+possibleEmail);
                    Log.e("permission", "granted Marshmallow O/S");

                } else {                        ActivityCompat.requestPermissions(PermissionActivity.this,
                            new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE,
                                    android.Manifest.permission.READ_PHONE_STATE,
                                    Manifest.permission.GET_ACCOUNTS,
                                    android.Manifest.permission.CAMERA}, 1);
                }
            } else {
// Lower then Marshmallow

                    String possibleEmail=null;

                     Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
                     Account[] accounts = AccountManager.get(PermissionActivity.this).getAccounts();
                     for (Account account : accounts) {
                         if (emailPattern.matcher(account.name).matches()) {
                             possibleEmail = account.name;
                             Log.e("keshav","possibleEmail"+possibleEmail);
                     }

                    Log.e("keshav","possibleEmail gjhh->"+possibleEmail);


            }
        }
    });

<usi-permesso android: nome = "android.permission.GET_ACCOUNTS" />
Keshav Gera,

1
Ottieni le risposte agli account non hanno funzionato per me (restituisci 0 account) e posso confermare che chiamare il codice in un pulsante di richiamata non ha fatto differenza.
csga5000,

Questo codice funziona ma recentemente ho problemi di tempo, quindi per favore controlla la nostra parte
Keshav Gera,

0

Aggiungi questa riga singola in manifest ( per autorizzazione )

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

Quindi incolla questo codice nella tua attività

private ArrayList<String> getPrimaryMailId() {
    ArrayList<String> accountsList = new ArrayList<String>();
    try {
        Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
        for (Account account : accounts) {
            accountsList.add(account.name);
            Log.e("GetPrimaryMailId ", account.name);
        }
    } catch (Exception e) {
        Log.e("GetPrimaryMailId", " Exception : " + e);
    }
    return accountsList;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.