Cara mendapatkan alamat email utama perangkat Android

412

Bagaimana Anda mendapatkan alamat email utama Android (atau daftar alamat email)?

Saya memahami bahwa pada OS 2.0+ ada dukungan untuk beberapa alamat email, tetapi di bawah 2.0 Anda hanya dapat memiliki satu alamat email per perangkat.

Brandon O'Rourke
sumber
Apakah Anda berbicara tentang mengambil alamat email kontak?
Austyn Mahoney
1
Tidak, alamat email utama perangkat.
Brandon O'Rourke
Ada satu atau lebih alamat email yang dikaitkan dengan perangkat Android, bukan? Itu yang saya inginkan.
Brandon O'Rourke
2
@ BrandonO'Rourke Maksud Anda "Alamat email primer perangkat" sebagai alamat yang terkait dengan Android Market? Karena ada perbedaan antara id gmail yang terkait dengan Android Market dan email lainnya. Lihat pertanyaan ini stackoverflow.com/questions/10606976/…
Gaurav Agarwal

Jawaban:

749

Ada beberapa cara untuk melakukan ini, ditunjukkan di bawah ini.

Sebagai peringatan yang bersahabat, berhati-hatilah dan terbuka untuk pengguna saat berurusan dengan akun, profil, dan data kontak. Jika Anda menyalahgunakan alamat email pengguna atau informasi pribadi lainnya, hal-hal buruk dapat terjadi.

Metode A: Gunakan AccountManager (API level 5+)

Anda dapat menggunakan AccountManager.getAccountsatau AccountManager.getAccountsByTypeuntuk mendapatkan daftar semua nama akun di perangkat. Untungnya, untuk jenis akun tertentu (termasuk com.google), nama akun adalah alamat email. Cuplikan contoh di bawah ini.

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

Perhatikan bahwa ini memerlukan GET_ACCOUNTSizin:

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

Lebih lanjut tentang penggunaan AccountManagerdapat ditemukan di kode sampel Contact Manager di SDK.

Metode B: Gunakan KontakContract.Profile (API level 14+)

Pada Android 4.0 (Ice Cream Sandwich), Anda bisa mendapatkan alamat email pengguna dengan mengakses profil mereka. Mengakses profil pengguna agak berat karena memerlukan dua izin (lebih lanjut tentang itu di bawah), tetapi alamat email adalah bagian data yang cukup sensitif, jadi ini adalah harga tiket masuk.

Di bawah ini adalah contoh lengkap yang menggunakan a CursorLoaderuntuk mengambil baris data profil yang berisi alamat email.

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

Ini membutuhkan izin READ_PROFILEdan READ_CONTACTS:

<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
Roman Nurik
sumber
3
Saya memiliki pertanyaan serupa menggunakan kode Anda. Saya bisa mendapatkan semua id gmail yang terkait dengan telepon saya tetapi saya ingin yang utama. Saya menemukan satu solusi seperti ketika kita menambahkan lebih banyak id surat untuk disinkronkan dengan telepon, ia masuk ke dalam tumpukan jika saya mendapatkan posisi ke-0 com.google id, saya mendapatkan yang utama karena masuk pertama dan memperoleh posisi ke-0 dalam tumpukan . Inilah beberapa kode saya Akun [] akun = AccountManager.get (ini) .getAccountsByType ("com.google"); String myEmailid = akun [0] .toString (); Log.d ("Id email saya yang saya inginkan", myEmailid); saya tahu ini bukan cara yang benar.
PiyushMishra
59
Metode profil cacat parah (menurut saya). Aplikasi yang ingin / membutuhkan email saya bukan masalah besar dibandingkan dengan aplikasi yang ingin membaca semua kontak saya, tetapi Anda membuatnya sehingga mereka berdua membutuhkan izin yang sama. Jadi sebagai pengguna, saya tidak bisa membedakan antara aplikasi yang akan membaca email saya, dan aplikasi yang akan membaca 500+ kontak saya. Ini adalah masalah yang sangat nyata dan praktis karena jumlah aplikasi yang menyalahgunakan kontak Anda bertambah!
Tom
3
@Muzikant Ini tidak berarti pernyataan resmi, tapi itu sesuatu yang tidak mungkin berubah. Karena itu, cara "benar" mengakses alamat email pengguna adalah Metode B. Itu lebih "resmi" dan fakta bahwa itu di belakang beberapa izin kelas berat harus menunjukkan sensitivitas yang dengannya Anda harus mendekati data tersebut.
Roman Nurik
15
Saya setuju dengan @Tom dalam hal ini. Meminta izin untuk data semua kontak di telepon hanya untuk Nama Depan dan Terakhir pengguna itu konyol.
tasomaniac
3
Metode B tidak berfungsi untuk saya di Android 4.4 menyalin semua kode contoh. cursor.isAfterLast()selalu mengembalikan true. Ada ide?
cprcrack
55

Ini bisa bermanfaat bagi orang lain:

Menggunakan AccountPicker untuk mendapatkan alamat email pengguna tanpa izin global apa pun, dan memungkinkan pengguna untuk mengetahui dan mengotorisasi atau membatalkan proses.

Jorge Cevallos
sumber
1
Ini adalah jawaban yang sangat membantu, saya pikir ini harus menjadi pilihan yang disukai karena Email Primer biasanya berarti Akun Google, yang pada gilirannya akan Anda miliki dalam hubungannya dengan Google Play
Alex.F
@ Alex.F Apakah ini berfungsi untuk versi android setelah / dari marshmellow?
Eswar
27

Saya akan menggunakan Android AccountPicker , yang diperkenalkan di ICS.

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

Dan kemudian tunggu hasilnya:

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
sumber
2
Perhatikan bahwa itu mengharuskan Anda untuk menggunakan layanan-bermain, dan bahwa itu akan menampilkan dialog dalam beberapa kasus, bahwa pengguna harus memilih akun.
Pengembang android
Menggunakan AccountManager.newChooseAccountIntent () melakukan pekerjaan yang sama dan tidak memerlukan pustaka layanan bermain.
Denis
Apakah ini menimbulkan pop up kepada pengguna untuk otentikasi akun dalam konteks versi android terbaru? Jika ya, bagaimana saya memotongnya untuk perangkat yang hanya memiliki satu akun?
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
sumber
Metode yang baik dan mudah Terima kasih :)
Talha Q
2
Perhatikan bahwa ini memerlukan android.permission.GET_ACCOUNTS, yang didefinisikan sebagai izin 'berbahaya' (memerlukan permintaan runtime): developer.android.com/reference/android/…
SagiLow
@ SagiLow Bagaimana Anda menangani ini? Saya tidak ingin meminta pengguna, untuk izin lain, hanya untuk membuatnya malas memasukkan alamat emailnya :)
kode
1
@berdasarkan saya tidak ... itu tidak mungkin sejauh yang saya tahu.
SagiLow
2
manager.getAccountsByType ("com.google"); tidak bekerja dengan versi Android yang lebih baru.
powder366
8

Ada api Android yang memungkinkan pengguna untuk memilih alamat email mereka tanpa perlu izin. Lihatlah: 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);
}

Ini akan menampilkan pemilih di mana pengguna dapat memilih alamat email. Hasilnya akan dikirim dalamonActivityResult()

Wirling
sumber
Saya dapat mengonfirmasi bahwa saya dapat menggunakan ini, terima kasih atas satu-satunya jawaban yang berhasil saya temukan
csga5000
Satu-satunya solusi yang bekerja, terima kasih berputar
Zulqarnain
7

Jawaban yang diterima dengan sedih tidak bekerja.

Saya terlambat, tapi inilah solusi untuk aplikasi Email Android internal kecuali konten uri diubah oleh penyedia:

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;
}
Hari Burak
sumber
2

Gunakan metode ini:

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

Perhatikan bahwa ini memerlukan GET_ACCOUNTSizin:

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

Kemudian:

editTextEmailAddress.setText(getUserEmail());
Iman Marashi
sumber
Ini sepertinya hanya mengembalikan akun yang terkait dengan aplikasi saat ini - jadi saya mendapatkan "tidak ada" dalam pengujian
csga5000
manager.getAccountsByType ("com.google") tidak berfungsi di Android versi terbaru. Dan dari mana App.getInstance ()?
powder366
0

Android dikunci GET_ACCOUNTSbaru - baru ini sehingga beberapa jawaban tidak bekerja untuk saya. Saya dapat ini bekerja di Android 7.0 dengan peringatan bahwa pengguna Anda harus menanggung dialog izin.

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
sumber
Ini tidak berbeda dari jawaban lain dan sepertinya itu tidak bekerja untuk saya - sepertinya karena dalam versi Android yang lebih baru ini hanya mengembalikan akun yang terkait dengan aplikasi dan tidak lagi memerlukan izin.
csga5000
0

Bekerja Di Sistem Operasi 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);


            }
        }
    });
Keshav Gera
sumber
<menggunakan-izin android: name = "android.permission.GET_ACCOUNTS" />
Keshav Gera
1
Dapatkan jawaban akun tidak berfungsi untuk saya (kembalikan 0 akun) - dan saya dapat mengonfirmasi bahwa memanggil kode dalam panggilan balik tombol tidak membuat perbedaan.
csga5000
Kode ini berfungsi tetapi baru-baru ini saya mempunyai masalah waktu jadi silakan periksa pihak kami
Keshav Gera
0

Tambahkan baris tunggal ini dalam manifes ( untuk izin )

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

Kemudian tempel kode ini dalam aktivitas Anda

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
sumber