发送电子邮件可用于Wifi,但不适用于移动网络

时间:2019-02-25 14:20:46

标签: java android email 3g 4g

我想发送电子邮件,如下面的代码:

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentActivity;
import android.view.View;

import com.etf.jhilal.etf.Fragments.ZDDFragment;
import com.etf.jhilal.etf.Other.InternetDetector;
import com.etf.jhilal.etf.R;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.model.Message;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;

public class GmailSend extends AsyncTask<Void, Void, String> {

    private com.google.api.services.gmail.Gmail mService = null;
    private FragmentActivity activity;
    private Exception mLastError = null;
    private GoogleAccountCredential mCredential;
    private ProgressDialog mprogress;
    private Context mctx;

    private String subject;
    private String body;

    public GmailSend(FragmentActivity activity, GoogleAccountCredential credential, final Context ctx, String sub, String bod) {
        HttpTransport transport = AndroidHttp.newCompatibleTransport();
        JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
        mService = new com.google.api.services.gmail.Gmail.Builder(
                transport, jsonFactory, credential)
                .setApplicationName(String.valueOf((R.string.app_name)))
                .build();
        this.activity = activity;
        this.mCredential = credential;
        this.mctx = ctx;
        this.subject = sub;
        this.body = bod;

        mprogress = new ProgressDialog(activity);
        mprogress.setMessage("Sending...");
    }

    @Override
    protected String doInBackground(Void... voids) {
        try {
            return getDataFromApi();
        } catch (Exception e) {
            mLastError = e;
            cancel(true);
            return null;
        }
    }

    private String getDataFromApi() throws IOException {
        // getting Values for to Address, from Address, Subject and Body
        String user = "me";
        String to = "jalalhilal0@gmail.com";
        String from = mCredential.getSelectedAccountName();
        MimeMessage mimeMessage;
        String response = "";
        try {
            mimeMessage = createEmail(to, from, subject, body);

            response = sendMessage(mService, user, mimeMessage);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return response;
    }

    // Method to send email
    private String sendMessage(Gmail service,
                               String userId,
                               MimeMessage email)
            throws MessagingException, IOException {
        Message message = createMessageWithEmail(email);
        // GMail's official method to send email with oauth2.0
        message = service.users().messages().send(userId, message).execute();

        System.out.println("Message id: " + message.getId());
        System.out.println(message.toPrettyString());
        return message.getId();
    }

    // Method to create email Params
    private MimeMessage createEmail(String to,
                                    String from,
                                    String subject,
                                    String bodyText) throws MessagingException {
        Properties props = new Properties();

        Session session = Session.getDefaultInstance(props, null);

        MimeMessage email = new MimeMessage(session);
        DataHandler handler = new DataHandler(new ByteArrayDataSource(bodyText.getBytes(), "text/plain"));
        InternetAddress tAddress = new InternetAddress(to);
        InternetAddress fAddress = new InternetAddress(from);

        email.setFrom(fAddress);
        email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress);
        email.setSubject(subject);
        email.setDataHandler(handler);
        email.setSentDate(new Date());

        // Create Multipart object and add MimeBodyPart objects to this object
        Multipart multipart = new MimeMultipart();

        // Changed for adding attachment and text
        // email.setText(bodyText);

        BodyPart textBody = new MimeBodyPart();
        textBody.setText(bodyText);
        multipart.addBodyPart(textBody);

        email.setContent(multipart);
        return email;
    }

    private Message createMessageWithEmail(MimeMessage email)
            throws MessagingException, IOException {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        email.writeTo(bytes);
        String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
        Message message = new Message();
        message.setRaw(encodedEmail);
        return message;
    }

    @Override
    protected void onPreExecute() {
            mprogress.show();
    }

    @Override
    protected void onPostExecute(String output) {
            mprogress.hide();
        /*if (output == null || output.length() == 0) {
            showMessage(view, "No results returned.");
        } else {*/


    }

    /*@Override
    protected void onCancelled() {
        mProgress.hide();
        if (mLastError != null) {
            if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
                showGooglePlayServicesAvailabilityErrorDialog(
                        ((GooglePlayServicesAvailabilityIOException) mLastError)
                                .getConnectionStatusCode());
            } else if (mLastError instanceof UserRecoverableAuthIOException) {
                startActivityForResult(
                        ((UserRecoverableAuthIOException) mLastError).getIntent(),
                        Utils.REQUEST_AUTHORIZATION);
            } else {
                showMessage(view, "The following error occurred:\n" + mLastError);
                Log.v("Error", mLastError + "");
            }
        } else {
            showMessage(view, "Request Cancelled.");
        }
    }*/
}

在mainactivity中,我使用此类(GmailSend)发送这样的电子邮件:

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.gmail.GmailScopes;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link ZDDFragment.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link ZDDFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class ZDDFragment extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    private InternetDetector internetDetector;

    private Spinner spinner;
    private TimePicker timePicker;
    private EditText editmarche;
    private FloatingActionButton fabsend;

    private Context ctxtest;
    private GoogleSignInAccount acct;
    private GoogleAccountCredential accountCredential;
    private static final String[] SCOPES = {
            GmailScopes.GMAIL_LABELS,
            GmailScopes.GMAIL_COMPOSE,
            GmailScopes.GMAIL_INSERT,
            GmailScopes.GMAIL_MODIFY,
            GmailScopes.GMAIL_READONLY,
            GmailScopes.MAIL_GOOGLE_COM
    };

    public ZDDFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment ZDDFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static ZDDFragment newInstance(String param1, String param2) {
        ZDDFragment fragment = new ZDDFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        final View v = inflater.inflate(R.layout.fragment_zdd, container, false);

        ctxtest = getContext();

        internetDetector = new InternetDetector(ctxtest);

        acct = GoogleSignIn.getLastSignedInAccount(this.getContext());

        accountCredential = GoogleAccountCredential.usingOAuth2(
                getContext(), Arrays.asList(SCOPES))
                .setSelectedAccountName(acct.getAccount().name)
                .setBackOff(new ExponentialBackOff());

        List exempleList = new ArrayList();
        exempleList.add("Aucun");
        exempleList.add("Formation tardive du train");
        exempleList.add("Régulation");
        exempleList.add("Panne machine");
        exempleList.add("Engagement chantier tardif");
        exempleList.add("Chantier rendu en retard");
        exempleList.add("Autres");

        ArrayAdapter adapter = new ArrayAdapter(
                getContext(),
                android.R.layout.simple_spinner_item,
                exempleList
        );

        timePicker = v.findViewById(R.id.timezd);
        timePicker.setIs24HourView(true);

        //Floating invisible avec le keyboard
        getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);

        editmarche = v.findViewById(R.id.editmarched);
        editmarche.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_ENTER) {
                    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(editmarche.getWindowToken(), 0);
                    editmarche.setFocusable(false);
                    editmarche.setFocusableInTouchMode(true);
                    editmarche.setCursorVisible(false);
                    return true;
                } else
                    return false;
            }
        });

        fabsend = v.findViewById(R.id.fab_zd);
        fabsend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!internetDetector.checkMobileInternetConn()) {
                    showMessage(getView(), "Pas de connexion Internet");
                } else
                    getResultsFromApi2(v);

                Fragment fragment = new ZDDFragment();
                if (fragment != null) {
                    FragmentTransaction ft = getFragmentManager().beginTransaction();
                    ft.replace(R.id.mainFrame, fragment);
                    ft.commit();
                }

            }
        });

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        spinner = v.findViewById(R.id.spinner_zd_d);

        spinner.setAdapter(adapter);

        return v;
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }

    private boolean isGooglePlayServicesAvailable() {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        int connectionStatusCode = apiAvailability.isGooglePlayServicesAvailable(getContext());
        return connectionStatusCode == ConnectionResult.SUCCESS;
    }

    private void acquireGooglePlayServices() {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        int connectionStatusCode = apiAvailability.isGooglePlayServicesAvailable(getContext());
        if (apiAvailability.isUserResolvableError(connectionStatusCode)) {
            showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
        }
    }

    void showGooglePlayServicesAvailabilityErrorDialog(final int connectionStatusCode) {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        Dialog dialog = apiAvailability.getErrorDialog(
                getActivity(),
                connectionStatusCode,
                Utils.REQUEST_GOOGLE_PLAY_SERVICES);
        dialog.show();
    }

    private void getResultsFromApi2(View view) {
        if (!isGooglePlayServicesAvailable()) {
            acquireGooglePlayServices();
        } /*else if (!internetDetector.checkMobileInternetConn()) {
            showMessage(view, "Pas de connection Internet...");
        } */ else {

            new MyTask();
            showMessage(getView(), "Message envoyé avec succés");
        }
    }

    private void showMessage(View view, String message) {
        Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
    }

    private class MyTask extends AsyncTask<Void, Void, String> {
        //used for database conection purpose
        String html = "Numéro de marche : " + editmarche.getText().toString() + "\nRetard (+5min) : " + spinner.getSelectedItem().toString() + "\nHeure : " + timePicker.getHour() + ":" + timePicker.getMinute();

        MyTask() {
            new GmailSend(getActivity(), accountCredential, ctxtest, "Zone Dense - Départ", html).execute();
        }
        // use the Cursor returned from the doInBackground method

        @Override
        protected String doInBackground(Void... voids) {
            new MyTask();
            return null;
        }

        @Override
        protected void onPreExecute() {

        }

        @Override
        protected void onPostExecute(String output) {
            if (MyTask.this.getStatus() == Status.FINISHED) {
                showMessage(getView().findViewById(android.R.id.content), "Message envoyé avec succés");
            }
        }
    }
}

针对GoogleAuthUtil的编辑查找解决方案:对于具有相同错误的人,只需添加以下代码,问题就不在GmailSend或Myactivity中,而是我使用GoogleSigninOptions时的登录活动(查看handleSignInResult,GoogleTokenResponse)

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class LoginActivity extends AppCompatActivity implements View.OnClickListener {

    private FloatingActionButton signin;
    private FloatingActionButton signout;
    private GoogleSignInClient mGoogleSignInClient;

    private static final String TAG = "SignInActivity";
    private static final int RC_SIGN_IN = 9001;

    private String[] permissions = {"android.permission.ACCESS_NETWORK_STATE",
                                    "android.permission.CALL_PHONE",
                                    "android.permission.WRITE_EXTERNAL_STORAGE",
                                    "android.permission.ACCESS_FINE_LOCATION",
                                    "android.permission.READ_PHONE_STATE",
                                    "android.permission.SYSTEM_ALERT_WINDOW",
                                    "android.permission.CAMERA",
                                    "android.permission.READ_EXTERNAL_STORAGE",
                                    "android.permission.GET_ACCOUNTS"};

    private ProgressDialog mprogress;
    private InternetDetector internetDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        int requestCode = 200;
        requestPermissions(permissions, requestCode);

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        internetDetector = new InternetDetector(getApplicationContext());

        signin = findViewById(R.id.signin);
        signout = findViewById(R.id.signout);

        signin.setImageResource(R.drawable.ic_lock_outline_black_24dp);

        signin.setOnClickListener(this);
        signout.setOnClickListener(this);

        String serverClientId = getString(R.string.server_client_id);

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestServerAuthCode(serverClientId)
                .requestEmail()
                .build();

        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

        if (GoogleSignIn.getLastSignedInAccount(this) != null)
            if (internetDetector.checkMobileInternetConn())
                signIn();
            else
                showMessage(findViewById(android.R.id.content),"Pas de connection internet");

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.signin:
                if (internetDetector.checkMobileInternetConn())
                    signIn();
                else
                    showMessage(findViewById(android.R.id.content),"Pas de connection internet");
                break;
            case R.id.signout:
                signOut();
                break;
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        // [START on_start_sign_in]
        // Check for existing Google Sign In account, if the user is already signed in
        // the GoogleSignInAccount will be non-null.
        GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
        updateUI(account);
        // [END on_start_sign_in]
    }

    private void signIn() {
        mprogress = ProgressDialog.show(this,
                "Connexion", "Veuillez patientez...", true);
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    private void signOut() {
        mGoogleSignInClient.signOut()
                .addOnCompleteListener(this, new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        // [START_EXCLUDE]
                        updateUI(null);
                        // [END_EXCLUDE]
                    }
                });
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            // The Task returned from this call is always completed, no need to attach
            // a listener.
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
            handleSignInResult(task);
        }


    }

    private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
        try {
            GoogleSignInAccount account = completedTask.getResult(ApiException.class);
            String authCode = account.getServerAuthCode();



// Exchange auth code for access token




            GoogleTokenResponse tokenResponse =
                    new GoogleAuthorizationCodeTokenRequest(
                            new NetHttpTransport(),
                            JacksonFactory.getDefaultInstance(),
                            "https://www.googleapis.com/oauth2/v4/token",
                            "enter client_id",
                           "enter_client_secret",
                            authCode, "")  // Specify the same redirect URI that you use with your web
                            // app. If you don't have a web version of your app, you can
                            // specify an empty string.
                            .execute();


            String test = "*******";
            String test1 = "******@gmail\\.com";
            String test2 = account.getEmail();
            String test3 = "*****@gmail\\.com";

            // Signed in successfully, show authenticated UI.
            if (test2.matches(test) || test2.matches(test1) || test2.matches(test3)) {
                startActivity(new Intent(LoginActivity.this, DrawerActivity.class));
            }
            // Signed in successfully, show authenticated UI.
            signout.setVisibility(View.GONE);
            signin.setImageResource(R.drawable.ic_lock_open_black_24dp);
            mprogress.dismiss();
        } catch (ApiException e) {
            // The ApiException status code indicates the detailed failure reason.
            // Please refer to the GoogleSignInStatusCodes class reference for more information.
            Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
            updateUI(null);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void updateUI(@Nullable GoogleSignInAccount account) {
        if (account != null) {
            signout.setVisibility(View.VISIBLE);
        } else {
            signout.setVisibility(View.GONE);
        }
    }

    private void showMessage(View view, String message) {
        Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
    }
}

0 个答案:

没有答案