So erhalten Sie die primäre E-Mail-Adresse des Android-Geräts

412

Wie erhalten Sie die primäre E-Mail-Adresse von Android (oder eine Liste mit E-Mail-Adressen)?

Nach meinem Verständnis werden unter OS 2.0+ mehrere E-Mail-Adressen unterstützt, aber unter 2.0 können Sie nur eine E-Mail-Adresse pro Gerät haben.

Brandon O'Rourke
quelle
Sprechen Sie über das Abrufen einer Kontakt-E-Mail-Adresse?
Austyn Mahoney
1
Nein, die primäre E-Mail-Adresse des Geräts.
Brandon O'Rourke
Es gibt eine oder mehrere E-Mail-Adressen, die mit einem Android-Gerät verknüpft sind, oder? Das würde ich wollen.
Brandon O'Rourke
2
@ BrandonO'Rourke Meinst du "die primäre E-Mail-Adresse des Geräts" als die mit dem Android Market verknüpfte? Weil es einen Unterschied zwischen der mit dem Android Market verknüpften Google Mail-ID und anderen E-Mails gibt. Werfen
Gaurav Agarwal

Antworten:

749

Es gibt verschiedene Möglichkeiten, dies zu tun (siehe unten).

Seien Sie als freundliche Warnung vorsichtig und offen gegenüber dem Benutzer, wenn Sie mit Konto-, Profil- und Kontaktdaten umgehen. Wenn Sie die E-Mail-Adresse eines Benutzers oder andere persönliche Informationen missbrauchen, können schlimme Dinge passieren.

Methode A: Verwenden Sie AccountManager (API Level 5+)

Sie können AccountManager.getAccountsoder verwenden AccountManager.getAccountsByType, um eine Liste aller Kontonamen auf dem Gerät abzurufen. Glücklicherweise sind die Kontonamen für bestimmte Kontotypen (einschließlich com.google) E-Mail-Adressen. Beispielausschnitt unten.

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;
        ...
    }
}

Beachten Sie, dass hierfür die GET_ACCOUNTSBerechtigung erforderlich ist :

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

Weitere Informationen zur Verwendung AccountManagerfinden Sie im Contact Manager Beispielcode im SDK.

Methode B: Verwenden Sie ContactsContract.Profile (API Level 14+)

Ab Android 4.0 (Ice Cream Sandwich) können Sie die E-Mail-Adressen des Benutzers abrufen, indem Sie auf sein Profil zugreifen. Der Zugriff auf das Benutzerprofil ist etwas schwerfällig, da zwei Berechtigungen erforderlich sind (mehr dazu weiter unten), aber E-Mail-Adressen sind ziemlich vertrauliche Daten, daher ist dies der Eintrittspreis.

Im Folgenden finden Sie ein vollständiges Beispiel, CursorLoaderin dem Profildatenzeilen mit E-Mail-Adressen mit a abgerufen werden.

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;
    }
}

Dies erfordert sowohl die READ_PROFILEals auch die READ_CONTACTSBerechtigungen:

<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
Roman Nurik
quelle
3
Ich habe eine ähnliche Frage mit Ihrem Code. Ich kann alle mit meinem Telefon verknüpften Google Mail-IDs abrufen, aber ich möchte die primäre. Ich habe eine Lösung gefunden, wie wenn wir mehr Mail-IDs hinzufügen, um sie mit dem Telefon zu synchronisieren. Wenn ich die 0. Position von com.google IDs erhalte, erhalte ich die primäre, weil sie zuerst eingegeben wird und die 0. Position in einem Stapel erhält . Hier ist mein Code Account [] accounts = AccountManager.get (this) .getAccountsByType ("com.google"); String myEmailid = accounts [0] .toString (); Log.d ("Meine E-Mail-ID, die ich möchte", myEmailid); Ich weiß, es ist nicht der richtige Weg.
PiyushMishra
59
Die Profilmethode ist (meiner Meinung nach) stark fehlerhaft. Eine App, die meine E-Mail möchte / benötigt, ist keine große Sache im Vergleich zu einer App, die alle meine Kontakte lesen möchte, aber Sie haben es so gemacht, dass beide die gleichen Berechtigungen benötigen. Als Benutzer kann ich den Unterschied zwischen einer App, die meine E-Mails liest, und einer App, die meine über 500 Kontakte liest, nicht erkennen. Dies ist ein sehr reales, praktisches Problem, da die Anzahl der Apps, die Ihre Kontakte missbrauchen, zunimmt!
Tom
3
@ Muzikant Es ist keineswegs eine offizielle Erklärung, aber es ist ziemlich unwahrscheinlich, dass sich daran etwas ändert. Die "richtige" Art, auf die E-Mail-Adressen eines Benutzers zuzugreifen, ist jedoch Methode B. Das ist "offizieller" und die Tatsache, dass es hinter einigen Schwergewichtsberechtigungen steckt, sollte die Sensibilität anzeigen, mit der Sie sich solchen Daten nähern sollten.
Roman Nurik
15
Ich stimme @Tom darin zu. Es ist lächerlich, nur nach dem Vor- und Nachnamen des Benutzers um Erlaubnis für die Daten aller Kontakte auf dem Telefon zu bitten.
Tasomaniac
3
Methode B funktioniert bei Android 4.4 nicht und kopiert den gesamten Beispielcode. cursor.isAfterLast()gibt immer true zurück. Irgendeine Idee?
Cprcrack
55

Dies könnte für andere nützlich sein:

Verwenden von AccountPicker, um die E-Mail-Adresse des Benutzers ohne globale Berechtigungen abzurufen und dem Benutzer zu ermöglichen, den Vorgang zu kennen und zu autorisieren oder abzubrechen.

Jorge Cevallos
quelle
1
Dies ist eine sehr hilfreiche Antwort. Ich denke, dies sollte die bevorzugte Option sein, da primäre E-Mail normalerweise das Google-Konto bedeutet, das Sie wiederum in Verbindung mit Google Play haben
Alex.F
@ Alex.F Funktioniert das für Android-Versionen nach / von Marshmellow?
Eswar
27

Ich würde den in ICS eingeführten AccountPicker von Android verwenden .

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

Und dann warten Sie auf das Ergebnis:

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);
    }
}
SeBsZ
quelle
2
Beachten Sie, dass Sie Spieldienste verwenden müssen und in einigen Fällen ein Dialogfeld angezeigt wird, in dem der Benutzer das Konto auswählen muss.
Android-Entwickler
Verwenden Sie AccountManager.newChooseAccountIntent (), um denselben Job auszuführen, und benötigen Sie nicht die Play-Services-Bibliothek.
Denis
Wird dem Benutzer ein Popup zur Kontoauthentifizierung im Kontext der neuesten Android-Version angezeigt? Wenn ja, wie kann ich das für ein Gerät mit nur einem Konto umgehen?
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;
}
Afzaal Iftikhar
quelle
Schöne und einfache Methode Danke :)
Talha Q
2
Beachten Sie, dass dies eine android.permission.GET_ACCOUNTS"gefährliche" Berechtigung erfordert (Laufzeitanforderung erforderlich): developer.android.com/reference/android/…
SagiLow
@SagiLow Wie bist du damit umgegangen? Ich möchte den Benutzer nicht um eine weitere Erlaubnis bitten, nur um ihn faul zu machen, seine E-Mail-Adresse einzugeben :)
Codebasiert
1
@codebased Ich habe nicht ... es ist meines Wissens nicht möglich.
SagiLow
2
manager.getAccountsByType ("com.google"); funktioniert nicht mit späteren Versionen von Android.
Pulver366
8

Es gibt eine Android-API, mit der der Benutzer seine E-Mail-Adresse ohne Erlaubnis auswählen kann. Schauen Sie sich Folgendes an: 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);
}

Dies zeigt eine Auswahl an, in der der Benutzer eine E-Mail-Adresse auswählen kann. Das Ergebnis wird in geliefertonActivityResult()

Verkabelung
quelle
Ich kann bestätigen, dass ich dies verwenden konnte, danke für die einzige funktionierende Antwort, die ich gefunden habe
csga5000
Die einzige funktionierende Lösung, danke Verkabelung
Zulqarnain
7

Leider funktioniert die akzeptierte Antwort nicht.

Ich bin spät dran, aber hier ist die Lösung für die interne Android-E-Mail-Anwendung, es sei denn, die Inhalts-URL wird vom Anbieter geändert:

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;
}
Burak Tag
quelle
2

Verwenden Sie diese Methode:

 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 "";
}

Beachten Sie, dass hierfür die GET_ACCOUNTSBerechtigung erforderlich ist :

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

Dann:

editTextEmailAddress.setText(getUserEmail());
Iman Marashi
quelle
Dies scheint nur Konten zurückzugeben, die mit der aktuellen App verknüpft sind - daher erhalte ich beim Testen "keine"
csga5000
manager.getAccountsByType ("com.google") funktioniert in späteren Versionen von Android nicht. Und woher kommt App.getInstance ()?
Pulver366
0

Android wurde GET_ACCOUNTSkürzlich gesperrt, sodass einige der Antworten bei mir nicht funktionierten. Ich habe dies auf Android 7.0 mit der Einschränkung funktioniert, dass Ihre Benutzer einen Berechtigungsdialog ertragen müssen.

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);
        }
    }
}
Patrick
quelle
Dies unterscheidet sich nicht von anderen Antworten und es funktioniert nicht für mich - anscheinend, weil in neueren Versionen von Android nur Konten zurückgegeben werden, die mit der App verknüpft sind, und keine Berechtigung mehr erforderlich ist.
csga5000
0

Arbeiten im MarshMallow-Betriebssystem

    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);


            }
        }
    });
Keshav Gera
quelle
<Verwendet-Erlaubnis android: name = "android.permission.GET_ACCOUNTS" />
Keshav Gera
1
Antworten auf Konten abrufen hat bei mir nicht funktioniert (0 Konten zurückgeben) - und ich kann bestätigen, dass das Aufrufen des Codes in einem Tastenrückruf keinen Unterschied gemacht hat.
csga5000
Dieser Code funktioniert, aber vor kurzem habe ich Zeitprobleme, also überprüfen Sie bitte unsere Seite
Keshav Gera
0

Fügen Sie diese einzelne Zeile im Manifest hinzu ( zur Erlaubnis )

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

Fügen Sie diesen Code dann in Ihre Aktivität ein

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;
}
Agilanbu
quelle