diff --git a/MyApplication2/.gitignore b/MyApplication2/.gitignore
new file mode 100644
index 0000000..c6cbe56
--- /dev/null
+++ b/MyApplication2/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/MyApplication2/.idea/.name b/MyApplication2/.idea/.name
new file mode 100644
index 0000000..4b528ed
--- /dev/null
+++ b/MyApplication2/.idea/.name
@@ -0,0 +1 @@
+EmailApp
\ No newline at end of file
diff --git a/MyApplication2/.idea/compiler.xml b/MyApplication2/.idea/compiler.xml
new file mode 100644
index 0000000..96cc43e
--- /dev/null
+++ b/MyApplication2/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/.idea/copyright/profiles_settings.xml b/MyApplication2/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..e7bedf3
--- /dev/null
+++ b/MyApplication2/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/.idea/gradle.xml b/MyApplication2/.idea/gradle.xml
new file mode 100644
index 0000000..1bbc21d
--- /dev/null
+++ b/MyApplication2/.idea/gradle.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/.idea/misc.xml b/MyApplication2/.idea/misc.xml
new file mode 100644
index 0000000..000e28a
--- /dev/null
+++ b/MyApplication2/.idea/misc.xml
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Android
+
+
+ Android Lint
+
+
+ CorrectnessLintAndroid
+
+
+ General
+
+
+ LintAndroid
+
+
+ Maven
+
+
+
+
+ Android
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.7
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/.idea/modules.xml b/MyApplication2/.idea/modules.xml
new file mode 100644
index 0000000..7ffac15
--- /dev/null
+++ b/MyApplication2/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/.idea/runConfigurations.xml b/MyApplication2/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/MyApplication2/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/.idea/vcs.xml b/MyApplication2/.idea/vcs.xml
new file mode 100644
index 0000000..6564d52
--- /dev/null
+++ b/MyApplication2/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/app/.gitignore b/MyApplication2/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/MyApplication2/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/MyApplication2/app/build.gradle b/MyApplication2/app/build.gradle
new file mode 100644
index 0000000..e88ab57
--- /dev/null
+++ b/MyApplication2/app/build.gradle
@@ -0,0 +1,45 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.2"
+
+ defaultConfig {
+ applicationId "com.adi.ho.jackie.emailapp"
+ minSdkVersion 16
+ targetSdkVersion 22
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ packagingOptions {
+ pickFirst 'META-INF/LICENSE.txt'
+// exclude 'META-INF/LICENSE.txt'
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile('com.google.api-client:google-api-client-android:1.20.0') {
+ exclude group: 'org.apache.httpcomponents'
+ }
+ compile 'com.android.support:appcompat-v7:23.1.1'
+ compile 'com.android.support:design:23.1.1'
+ compile 'com.google.android.gms:play-services-identity:8.4.0'
+ compile 'com.google.apis:google-api-services-gmail:v1-rev37-1.21.0'
+ compile 'com.android.support:recyclerview-v7:23.1.1'
+ compile 'com.android.support:cardview-v7:23.1.1'
+ compile 'com.android.support:support-v4:23.1.1'
+ compile 'com.google.android.gms:play-services-auth:8.4.0'
+// compile 'javax.mail:javax.mail-api:1.5.5'
+ compile 'com.sun.mail:android-mail:1.5.5'
+ compile 'com.sun.mail:android-activation:1.5.5'
+ compile 'org.jsoup:jsoup:1.7.2'
+
+}
diff --git a/MyApplication2/app/client_id.json b/MyApplication2/app/client_id.json
new file mode 100644
index 0000000..6d3087f
--- /dev/null
+++ b/MyApplication2/app/client_id.json
@@ -0,0 +1,13 @@
+{
+ "installed": {
+ "client_id": "408246309715-6r5ck2t5jfjfs5roi40id6em28uqb5v5.apps.googleusercontent.com",
+ "project_id": "industrial-gist-123219",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://accounts.google.com/o/oauth2/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "redirect_uris": [
+ "urn:ietf:wg:oauth:2.0:oob",
+ "http://localhost"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/MyApplication2/app/client_secret.json b/MyApplication2/app/client_secret.json
new file mode 100644
index 0000000..abec691
--- /dev/null
+++ b/MyApplication2/app/client_secret.json
@@ -0,0 +1 @@
+{"installed":{"client_id":"408246309715-6r5ck2t5jfjfs5roi40id6em28uqb5v5.apps.googleusercontent.com","project_id":"industrial-gist-123219","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
\ No newline at end of file
diff --git a/MyApplication2/app/proguard-rules.pro b/MyApplication2/app/proguard-rules.pro
new file mode 100644
index 0000000..abda49d
--- /dev/null
+++ b/MyApplication2/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/JHADI/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/MyApplication2/app/src/androidTest/java/com/adi/ho/jackie/emailapp/ApplicationTest.java b/MyApplication2/app/src/androidTest/java/com/adi/ho/jackie/emailapp/ApplicationTest.java
new file mode 100644
index 0000000..8f0799b
--- /dev/null
+++ b/MyApplication2/app/src/androidTest/java/com/adi/ho/jackie/emailapp/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.adi.ho.jackie.emailapp;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/MyApplication2/app/src/main/AndroidManifest.xml b/MyApplication2/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c6327c3
--- /dev/null
+++ b/MyApplication2/app/src/main/AndroidManifest.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/Email.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/Email.java
new file mode 100644
index 0000000..126ea57
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/Email.java
@@ -0,0 +1,54 @@
+package com.adi.ho.jackie.emailapp;
+
+import java.util.HashMap;
+
+/**
+ * Created by JHADI on 2/25/16.
+ */
+public class Email {
+
+ private String id;
+ private String snippet;
+ private String sender;
+ private String date;
+ private String body;
+ private String recipient;
+ private String favorite;
+ private String subject;
+
+ public Email (HashMap emailHeader){
+ id = emailHeader.get("ID");
+ snippet = emailHeader.get("SNIPPET");
+ sender = emailHeader.get("SENDER");
+ date = emailHeader.get("DATE");
+ body = emailHeader.get("BODY");
+ recipient = emailHeader.get("RECIPIENT");
+ favorite = emailHeader.get("FAVORITE");
+ subject = emailHeader.get("SUBJECT");
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getSnippet() {
+ return snippet;
+ }
+
+ public String getSender() {
+ return sender;
+ }
+
+ public String getDate() {
+ return date;
+ }
+
+ public String getBody(){ return body;}
+
+ public String getRecipient(){ return recipient;}
+
+ public String getFavorite(){return favorite;}
+
+ public String getSubject(){return subject;}
+
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailDraft.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailDraft.java
new file mode 100644
index 0000000..31af0b3
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailDraft.java
@@ -0,0 +1,38 @@
+package com.adi.ho.jackie.emailapp;
+
+import java.util.HashMap;
+
+/**
+ * Created by JHADI on 2/28/16.
+ */
+public class EmailDraft {
+
+ private String recipient;
+ private String subject;
+ private String body;
+ private String id;
+
+ public EmailDraft(HashMap hashMap){
+ recipient = hashMap.get("RECIPIENT");
+ subject = hashMap.get("SUBJECT");
+ body = hashMap.get("BODY");
+ id = hashMap.get("ID");
+
+ }
+
+ public String getRecipient() {
+ return recipient;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public String getId() {
+ return id;
+ }
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemDetailActivity.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemDetailActivity.java
new file mode 100644
index 0000000..89c9b91
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemDetailActivity.java
@@ -0,0 +1,156 @@
+package com.adi.ho.jackie.emailapp;
+
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.v7.widget.Toolbar;
+import android.text.Html;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.app.ActionBar;
+import android.view.MenuItem;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.adi.ho.jackie.emailapp.database.MailDatabaseOpenHelper;
+import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
+
+import java.util.HashMap;
+
+/**
+ * An activity representing a single EmailItem detail screen. This
+ * activity is only used narrow width devices. On tablet-size devices,
+ * item details are presented side-by-side with a list of items
+ * in a {@link EmailItemListActivity}.
+ */
+public class EmailItemDetailActivity extends AppCompatActivity {
+
+ private String mRecipient;
+ private String mSender;
+ private String mDate;
+ private String mBody;
+ private String mId;
+ private String mSubject;
+
+ public TextView mSenderText;
+ public TextView mRecipientText;
+ public TextView mDateText;
+ public TextView mBodyText;
+ public TextView mSubjectText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_emailitem_detail);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar);
+ setSupportActionBar(toolbar);
+
+ mBodyText = (TextView) findViewById(R.id.email_body_detail);
+ mDateText = (TextView) findViewById(R.id.email_date_detail);
+ mRecipientText = (TextView) findViewById(R.id.email_recipient_detail);
+ mSenderText = (TextView) findViewById(R.id.email_sender_detail);
+ mSubjectText = (TextView)findViewById(R.id.email_subject_detail);
+
+ mId = getIntent().getStringExtra("EMAILID");
+
+
+ // Show the Up button in the action bar.
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ new GetEmailFromDBWithIdAsyncTask().execute(mId);
+
+ // savedInstanceState is non-null when there is fragment state
+ // saved from previous configurations of this activity
+ // (e.g. when rotating the screen from portrait to landscape).
+ // In this case, the fragment will automatically be re-added
+ // to its container so we don't need to manually add it.
+ // For more information, see the Fragments API guide at:
+ //
+ // http://developer.android.com/guide/components/fragments.html
+ //
+ if (savedInstanceState == null && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ // Create the detail fragment and add it to the activity
+ // using a fragment transaction.
+ Bundle arguments = new Bundle();
+ arguments.putString("ID",mId);
+ EmailItemDetailFragment fragment = new EmailItemDetailFragment();
+ fragment.setArguments(arguments);
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.emailitem_detail_container, fragment)
+ .commit();
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ // This ID represents the Home or Up button. In the case of this
+ // activity, the Up button is shown. For
+ // more details, see the Navigation pattern on Android Design:
+ //
+ // http://developer.android.com/design/patterns/navigation.html#up-vs-back
+ //
+ navigateUpTo(new Intent(this, EmailItemListActivity.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private class GetEmailFromDBWithIdAsyncTask extends AsyncTask> {
+ MailDatabaseOpenHelper helper;
+ HashMap emailIdContents;
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ helper = MailDatabaseOpenHelper.getInstance(EmailItemDetailActivity.this);
+ emailIdContents = new HashMap<>();
+ }
+
+ @Override
+ protected HashMap doInBackground(String... params) {
+ String id = params[0];
+ Cursor cursor = helper.getEmailById(id);
+ cursor.moveToFirst();
+ emailIdContents.put("RECIPIENT", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_RECIPIENT)));
+ emailIdContents.put("SENDER", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SENDER)));
+ emailIdContents.put("BODY", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_BODY)));
+ emailIdContents.put("DATE", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_DATE)));
+ emailIdContents.put("SUBJECT", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SUBJECT)));
+ cursor.close();
+ return emailIdContents;
+ }
+
+ @Override
+ protected void onPostExecute(HashMap hashMap) {
+ mBody = hashMap.get("BODY").toString();
+ mDate = hashMap.get("DATE").toString();
+ mRecipient = hashMap.get("RECIPIENT").toString();
+ mSender = hashMap.get("SENDER").toString();
+ mSubject = hashMap.get("SUBJECT").toString();
+
+
+ mSenderText.setText(mSender);
+ mRecipientText.setText(mRecipient);
+ mDateText.setText("Date Received: " + mDate);
+ mSubjectText.setText(mSubject);
+ if (mBody.contains("html")) {
+ mBodyText.setText(Html.fromHtml(mBody));
+ } else {
+ mBodyText.setText(mBody);
+ }
+
+ }
+ }
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemDetailFragment.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemDetailFragment.java
new file mode 100644
index 0000000..e0efbb1
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemDetailFragment.java
@@ -0,0 +1,134 @@
+package com.adi.ho.jackie.emailapp;
+
+import android.app.Activity;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.support.design.widget.CollapsingToolbarLayout;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Html;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.adi.ho.jackie.emailapp.database.MailDatabaseOpenHelper;
+
+import org.w3c.dom.Text;
+
+import java.util.HashMap;
+
+/**
+ * A fragment representing a single EmailItem detail screen.
+ * This fragment is either contained in a {@link EmailItemListActivity}
+ * in two-pane mode (on tablets) or a {@link EmailItemDetailActivity}
+ * on handsets.
+ */
+public class EmailItemDetailFragment extends Fragment {
+ /**
+ * The fragment argument representing the item ID that this fragment
+ * represents.
+ */
+ private String mRecipient;
+ private String mSender;
+ private String mDate;
+ private String mBody;
+ private String mId;
+ private String mSubject;
+
+ public TextView mSenderText;
+ public TextView mRecipientText;
+ public TextView mDateText;
+ public TextView mBodyText;
+ public TextView mSubjectText;
+
+ public EmailItemDetailFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (getArguments().containsKey("ID") ){
+// // Load the dummy content specified by the fragment
+// // arguments. In a real-world scenario, use a Loader
+// // to load content from a content provider.
+ mId = (getArguments().getString("ID"));
+
+ } else {
+
+ }
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.emailitem_detail, container, false);
+
+ mSenderText = (TextView) rootView.findViewById(R.id.email_sender_detail);
+ mRecipientText = (TextView)rootView.findViewById(R.id.email_recipient_detail);
+ mDateText = (TextView)rootView.findViewById(R.id.email_date_detail);
+ mBodyText= (TextView)rootView.findViewById(R.id.email_body_detail);
+ mSubjectText = (TextView)rootView.findViewById(R.id.email_subject_detail);
+
+ // Show the dummy content as text in a TextView.
+
+ return rootView;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mId != null) {
+ new GetEmailFromDBWithIdAsyncTask().execute(mId);
+ }
+ }
+
+ private class GetEmailFromDBWithIdAsyncTask extends AsyncTask> {
+ MailDatabaseOpenHelper helper;
+ HashMap emailIdContents;
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ helper = MailDatabaseOpenHelper.getInstance(getContext());
+ emailIdContents = new HashMap<>();
+ }
+
+ @Override
+ protected HashMap doInBackground(String... params) {
+ String id = params[0];
+ Cursor cursor = helper.getEmailById(id);
+ cursor.moveToFirst();
+ emailIdContents.put("RECIPIENT", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_RECIPIENT)));
+ emailIdContents.put("SENDER", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SENDER)));
+ emailIdContents.put("BODY", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_BODY)));
+ emailIdContents.put("DATE", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_DATE)));
+ emailIdContents.put("SUBJECT", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SUBJECT)));
+ cursor.close();
+ return emailIdContents;
+ }
+
+ @Override
+ protected void onPostExecute(HashMap hashMap) {
+ mBody = hashMap.get("BODY").toString();
+ mDate = hashMap.get("DATE").toString();
+ mRecipient = hashMap.get("RECIPIENT").toString();
+ mSender = hashMap.get("SENDER").toString();
+ mSubject = hashMap.get("SUBJECT").toString();
+
+
+ mSenderText.setText(mSender);
+ mRecipientText.setText(mRecipient);
+ mDateText.setText("Date Received: " + mDate);
+ mSubjectText.setText(mSubject);
+ if (mBody.contains("html")) {
+ mBodyText.setText(Html.fromHtml(mBody));
+ } else {
+ mBodyText.setText(mBody);
+ }
+
+ }
+ }
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemListActivity.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemListActivity.java
new file mode 100644
index 0000000..ec30aa1
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/EmailItemListActivity.java
@@ -0,0 +1,860 @@
+package com.adi.ho.jackie.emailapp;
+
+import android.accounts.AccountManager;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.app.SearchManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.SearchView;
+import android.support.v7.widget.Toolbar;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+
+import com.adi.ho.jackie.emailapp.Fragments.ComposeFragment;
+import com.adi.ho.jackie.emailapp.database.MailDatabaseOpenHelper;
+import com.adi.ho.jackie.emailapp.recyclerlistitems.DividerItemDecoration;
+import com.adi.ho.jackie.emailapp.recyclerlistitems.EmailRecyclerAdapter;
+import com.adi.ho.jackie.emailapp.recyclerlistitems.EmailViewHolder;
+import com.adi.ho.jackie.emailapp.recyclerlistitems.VerticalSpaceItemDecoration;
+import com.google.android.gms.auth.GoogleAuthException;
+import com.google.android.gms.auth.GoogleAuthUtil;
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GooglePlayServicesUtil;
+import com.google.api.client.auth.openidconnect.IdToken;
+import com.google.api.client.extensions.android.http.AndroidHttp;
+import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
+import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
+import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
+import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
+import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
+import com.google.api.client.http.HttpTransport;
+import com.google.api.client.json.jackson2.JacksonFactory;
+import com.google.api.client.repackaged.org.apache.commons.codec.binary.StringUtils;
+import com.google.api.client.util.ExponentialBackOff;
+import com.google.api.services.gmail.Gmail;
+import com.google.api.services.gmail.GmailRequest;
+import com.google.api.services.gmail.GmailScopes;
+import com.google.api.services.gmail.model.Draft;
+import com.google.api.services.gmail.model.Label;
+import com.google.api.services.gmail.model.ListLabelsResponse;
+import com.google.api.services.gmail.model.ListMessagesResponse;
+import com.google.api.services.gmail.model.Message;
+import com.google.api.services.gmail.model.MessagePart;
+import com.google.api.services.gmail.model.MessagePartHeader;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+
+import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64;
+
+import javax.mail.BodyPart;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.jsoup.Jsoup;
+
+import javax.net.ssl.HttpsURLConnection;
+
+/**
+ * An activity representing a list of EmailItems. This activity
+ * has different presentations for handset and tablet-size devices. On
+ * handsets, the activity presents a list of items, which when touched,
+ * lead to a {@link EmailItemDetailActivity} representing
+ * item details. On tablets, the activity presents the list of items and
+ * item details side-by-side using two vertical panes.
+ */
+public class EmailItemListActivity extends AppCompatActivity implements ComposeFragment.SendEmailTaskListener, EmailViewHolder.MakeSecondFragmentListener, ComposeFragment.SaveDraftsListener {
+ public GoogleAccountCredential mCredential;
+ ProgressDialog mProgress;
+ EmailRecyclerAdapter mEmailRecyclerAdapter;
+ private List mEmailIdsList;
+ private ArrayList mEmailMessages;
+ SearchView searchView;
+ static final int REQUEST_ACCOUNT_PICKER = 1000;
+ static final int REQUEST_AUTHORIZATION = 1001;
+ static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
+ private static final String PREF_ACCOUNT_NAME = "accountName";
+ private static final String[] SCOPES = {GmailScopes.GMAIL_READONLY, GmailScopes.GMAIL_COMPOSE, GmailScopes.GMAIL_INSERT, GmailScopes.GMAIL_LABELS, GmailScopes.GMAIL_MODIFY, GmailScopes.GMAIL_SEND, GmailScopes.MAIL_GOOGLE_COM};
+ /**
+ * Whether or not the activity is in two-pane mode, i.e. running on a tablet
+ * device.
+ */
+ public boolean mTwoPane;
+ RecyclerView emaillistRecycler;
+ private MailDatabaseOpenHelper mHelper;
+ private EmailRecyclerAdapter emailRecyclerAdapter;
+ private List mRecyclerViewList;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mProgress = new ProgressDialog(this);
+ mProgress.setMessage("Calling Gmail API ...");
+ setContentView(R.layout.activity_emailitem_list);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ toolbar.setTitle(getTitle());
+ mEmailMessages = new ArrayList<>();
+ mRecyclerViewList = new ArrayList<>();
+ emaillistRecycler = (RecyclerView) findViewById(R.id.emailitem_list);
+ final FrameLayout composeFragmentContainer = (FrameLayout) findViewById(R.id.compose_fragment_container);
+ final FrameLayout frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
+
+
+ final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ ComposeFragment composeFragment = new ComposeFragment();
+ // fragmentTransaction.commit();
+ android.app.FragmentManager fm = getFragmentManager();
+ composeFragment.show(fm, "Compose");
+ }
+ });
+
+
+ if (findViewById(R.id.emailitem_detail_container) != null) {
+ // The detail container view will be present only in the
+ // large-screen layouts (res/values-w900dp).
+ // If this view is present, then the
+ // activity should be in two-pane mode.
+ mTwoPane = true;
+ }
+
+
+ // Initialize credentials and service object.
+ SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
+ mCredential = GoogleAccountCredential.usingOAuth2(
+ getApplicationContext(), Arrays.asList(SCOPES))
+ .setBackOff(new ExponentialBackOff())
+ .setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
+
+
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
+ searchView.setOnQueryTextListener(queryListener);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ return true;
+ } else if (id == R.id.action_refresh) {
+ if (isGooglePlayServicesAvailable()) {
+ refreshResults();
+ }
+ } else if (id == R.id.action_logout) {
+
+ List emptyList = new ArrayList<>();
+ mEmailRecyclerAdapter = new EmailRecyclerAdapter(EmailItemListActivity.this, mRecyclerViewList);
+ emaillistRecycler.setAdapter(emailRecyclerAdapter);
+ mEmailRecyclerAdapter.animateTo(emptyList);
+ chooseAccount();
+ mHelper.clearDb();
+ if (isGooglePlayServicesAvailable()) {
+ refreshResults();
+ }
+ } else if (id == R.id.action_search) {
+
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+
+ SearchView.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ if (query.trim().isEmpty() || query == null){
+ new LoadEmailsFromDbAsyncTask().execute();
+ } else {
+ new SearchEmailAsyncTask().execute(query);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ return false;
+ }
+ };
+
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ switch (requestCode) {
+ case REQUEST_GOOGLE_PLAY_SERVICES:
+ if (resultCode != RESULT_OK) {
+ isGooglePlayServicesAvailable();
+ }
+ break;
+ case REQUEST_ACCOUNT_PICKER:
+ if (resultCode == RESULT_OK && data != null &&
+ data.getExtras() != null) {
+ String accountName =
+ data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
+ if (accountName != null) {
+ mCredential.setSelectedAccountName(accountName);
+ SharedPreferences settings =
+ getPreferences(Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putString(PREF_ACCOUNT_NAME, accountName);
+ editor.apply();
+ }
+ } else if (resultCode == RESULT_CANCELED) {
+ Toast.makeText(EmailItemListActivity.this, "Account unspecified", Toast.LENGTH_SHORT).show();
+ }
+ break;
+ case REQUEST_AUTHORIZATION:
+ if (resultCode != RESULT_OK) {
+ chooseAccount();
+ }
+ break;
+ }
+
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+ private void refreshResults() {
+ if (mCredential.getSelectedAccountName() == null) {
+ chooseAccount();
+
+ } else {
+ if (isDeviceOnline()) {
+ new DownloadEmailAsyncTask(mCredential).execute();
+ //new MakeRequestTask(mCredential).execute();
+
+ } else {
+ Toast.makeText(EmailItemListActivity.this, "No network connection", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ private void chooseAccount() {
+ startActivityForResult(
+ mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
+
+ }
+
+ private boolean isDeviceOnline() {
+ ConnectivityManager connMgr =
+ (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
+ return (networkInfo != null && networkInfo.isConnected());
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ //Check if db is empty
+ mHelper = MailDatabaseOpenHelper.getInstance(EmailItemListActivity.this);
+ String count = "SELECT count(*) FROM EMAILS";
+ Cursor cursorCount = mHelper.getReadableDatabase().rawQuery(count, null);
+ cursorCount.moveToFirst();
+ int icount = cursorCount.getInt(0);
+
+ if (isGooglePlayServicesAvailable() && icount == 0) {
+ refreshResults();
+ } else if (icount > 0) {
+ new LoadEmailsFromDbAsyncTask().execute();
+ }
+ }
+
+ private boolean isGooglePlayServicesAvailable() {
+ final int connectionStatusCode =
+ GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
+ if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
+ showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
+ return false;
+ } else if (connectionStatusCode != ConnectionResult.SUCCESS) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Display an error dialog showing that Google Play Services is missing
+ * or out of date.
+ *
+ * @param connectionStatusCode code describing the presence (or lack of)
+ * Google Play Services on this device.
+ */
+ void showGooglePlayServicesAvailabilityErrorDialog(
+ final int connectionStatusCode) {
+ Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
+ connectionStatusCode,
+ EmailItemListActivity.this,
+ REQUEST_GOOGLE_PLAY_SERVICES);
+ dialog.show();
+ }
+
+ @Override
+ public void sendEmail(HashMap hashMap) {
+ SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
+ mCredential = GoogleAccountCredential.usingOAuth2(
+ getApplicationContext(), Arrays.asList(SCOPES))
+ .setBackOff(new ExponentialBackOff())
+ .setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
+ new SendEmailAsyncTask(mCredential).execute(hashMap);
+ }
+
+ @Override
+ public void makeSecondFragment(String emailId) {
+
+ //For two panes
+ Bundle bundle = new Bundle();
+ bundle.putString("ID", emailId);
+ EmailItemDetailFragment emailItemDetailFragment = new EmailItemDetailFragment();
+ emailItemDetailFragment.setArguments(bundle);
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+ fragmentTransaction.replace(R.id.emailitem_detail_container, emailItemDetailFragment);
+ fragmentTransaction.addToBackStack(null);
+ fragmentTransaction.commit();
+ }
+
+ private class MakeRequestTask extends AsyncTask, Email, List> {
+ private com.google.api.services.gmail.Gmail mService = null;
+ private Exception mLastError = null;
+ private HashMap emailHash;
+ String date;
+ private GoogleAccountCredential usercred;
+
+ public MakeRequestTask(GoogleAccountCredential credential) {
+
+ HttpTransport transport = AndroidHttp.newCompatibleTransport();
+ com.google.api.client.json.JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
+ mService = new com.google.api.services.gmail.Gmail.Builder(
+ transport, jsonFactory, credential)
+ .setApplicationName("Gmail API Android")
+ .build();
+ usercred = credential;
+ emailHash = new HashMap<>();
+
+ }
+
+ @Override
+ protected List doInBackground(ArrayList... params) {
+
+ List emailHeaderList = new ArrayList<>();
+ ArrayList idStrings = new ArrayList<>();
+ idStrings = params[0];
+ try {
+ for (String id : idStrings) {
+ Message message = mService.users().messages().get("me", id).execute();
+ for (MessagePartHeader messagePartHeader : message.getPayload().getHeaders()) {
+
+ if (messagePartHeader.getName().equals("From")) {
+ String sender = messagePartHeader.getValue();
+ emailHash.put("SENDER", sender);
+ }
+ if (messagePartHeader.getName().equals("Date")) {
+ date = messagePartHeader.getValue().substring(0, 11);
+ emailHash.put("DATE", date);
+ }
+
+ if (messagePartHeader.getName().equals("Delivered-To")) {
+ emailHash.put("RECIPIENT", messagePartHeader.getValue());
+ }
+ if (messagePartHeader.getName().equals("Subject")) {
+ emailHash.put("SUBJECT", messagePartHeader.getValue());
+ }
+ }
+
+
+ MessagePart firstMessagePart;
+ if (message.getPayload().getParts() != null) {
+ firstMessagePart = message.getPayload().getParts().get(0);
+ String emailBody = StringUtils.newStringUtf8(Base64.decodeBase64(firstMessagePart.getBody().getData()));
+ emailHash.put("BODY", emailBody);
+ } else {
+ String emailBody = StringUtils.newStringUtf8(Base64.decodeBase64(message.getPayload().getBody().getData()));
+ emailHash.put("BODY", emailBody);
+
+ }
+
+ emailHash.put("SNIPPET", message.getSnippet());
+ emailHash.put("ID", id);
+ emailHash.put("DRAFT", "0");
+
+ Email email = new Email(emailHash);
+ emailHeaderList.add(email);
+ publishProgress(email);
+
+ Log.i("EMAILS", "Added email id: " + id);
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return emailHeaderList;
+ }
+
+ //Insert each email into database
+ @Override
+ protected void onProgressUpdate(Email... values) {
+ super.onProgressUpdate(values);
+ new InsertEmailDBAsyncTask().execute(values[0]);
+ }
+
+ @Override
+ protected void onPreExecute() {
+ // mOutputText.setText("");
+ mProgress.show();
+ }
+
+ @Override
+ protected void onPostExecute(List output) {
+ mProgress.hide();
+ if (output == null || output.size() == 0) {
+ Toast.makeText(EmailItemListActivity.this, "No emails", Toast.LENGTH_SHORT).show();
+ // mOutputText.setText("No results returned.");
+ } else {
+ setRecyclerView(output);
+ //mOutputText.setText(TextUtils.join("\n", output));
+ }
+ }
+
+ @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(),
+ EmailItemListActivity.REQUEST_AUTHORIZATION);
+ } else {
+ // mOutputText.setText("The following error occurred:\n"
+// + mLastError.getMessage());
+ }
+ } else {
+ // mOutputText.setText("Request cancelled.");
+ }
+ }
+ }
+
+ private class DownloadEmailAsyncTask extends AsyncTask> {
+ private com.google.api.services.gmail.Gmail mService = null;
+ String emailIdData;
+ ArrayList emailIds;
+
+ public DownloadEmailAsyncTask(GoogleAccountCredential credential) {
+
+ HttpTransport transport = AndroidHttp.newCompatibleTransport();
+ com.google.api.client.json.JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
+ mService = new com.google.api.services.gmail.Gmail.Builder(
+ transport, jsonFactory, credential)
+ .setApplicationName("Gmail API Android")
+ .build();
+ emailIds = new ArrayList<>();
+ }
+
+ @Override
+ protected ArrayList doInBackground(Void... params) {
+ try {
+ ArrayList messageList = new ArrayList<>();
+ List labelIds = new ArrayList<>();
+ labelIds.add("INBOX"); //Retrieve inbox messages only
+ ListMessagesResponse messages = mService.users().messages().list("me").setLabelIds(labelIds).execute();
+
+ for (int i = 0; i < 100; i++) {
+ messageList.add(messages.getMessages().get(i));
+ }
+
+ for (Message message : messageList) {
+ emailIds.add(message.getId());
+ //mEmailMessages.add(message);
+ }
+
+ int i = 2;
+
+ } catch (Throwable tho) {
+ if (tho instanceof UserRecoverableAuthIOException) {
+ startActivityForResult(((UserRecoverableAuthIOException) tho).getIntent(), REQUEST_AUTHORIZATION);
+ } else {
+ tho.printStackTrace();
+ }
+ }
+
+ return emailIds;
+ }
+
+ @Override
+ protected void onPostExecute(ArrayList ids) {
+ //Send ids to list
+ mEmailIdsList = ids;
+ new MakeRequestTask(mCredential).execute(ids);
+
+ }
+ }
+
+ //Save emails to database
+ private class InsertEmailDBAsyncTask extends AsyncTask {
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ //mHelper = MailDatabaseOpenHelper.getInstance(EmailItemListActivity.this);
+
+ }
+
+ @Override
+ protected Void doInBackground(Email... params) {
+ mHelper.addEmailsToDatabase(params[0]);
+ return null;
+ }
+ }
+
+ private class LoadEmailsFromDbAsyncTask extends AsyncTask> {
+ HashMap emailHashFromDb;
+ List emailListFromDb;
+
+ public LoadEmailsFromDbAsyncTask() {
+ emailHashFromDb = new HashMap<>();
+ emailListFromDb = new ArrayList<>();
+ }
+
+ @Override
+ protected List doInBackground(Void... params) {
+ //mHelper = MailDatabaseOpenHelper.getInstance(EmailItemListActivity.this);
+ Cursor cursor = mHelper.getAllEmailsFromDb();
+ cursor.moveToFirst();
+ while (!cursor.isAfterLast()) {
+ emailHashFromDb.clear();
+ emailHashFromDb.put("SENDER", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SENDER)));
+ emailHashFromDb.put("DATE", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_DATE)));
+ emailHashFromDb.put("SUBJECT", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SUBJECT)));
+ emailHashFromDb.put("ID", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_ID)));
+ emailHashFromDb.put("SNIPPET", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SNIPPET)));
+ emailHashFromDb.put("DRAFT", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_DRAFT)));
+ emailListFromDb.add(new Email(emailHashFromDb));
+ cursor.moveToNext();
+ }
+ cursor.close();
+ return emailListFromDb;
+ }
+
+ @Override
+ protected void onPostExecute(List emailList) {
+// mCursor.close();
+ if (emailList == null || emailList.size() == 0) {
+ //TODO: display message
+ } else {
+ setRecyclerView(emailList);
+ }
+ }
+ }
+
+ private class SendEmailAsyncTask extends AsyncTask {
+ private com.google.api.services.gmail.Gmail mService = null;
+ private GoogleAccountCredential googleCredentials;
+
+ public SendEmailAsyncTask(GoogleAccountCredential credential) {
+ HttpTransport transport = AndroidHttp.newCompatibleTransport();
+ com.google.api.client.json.JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
+ mService = new com.google.api.services.gmail.Gmail.Builder(
+ transport, jsonFactory, credential)
+ .setApplicationName("Gmail API Android")
+ .build();
+ googleCredentials = credential;
+ }
+
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+
+ Snackbar.make(findViewById(android.R.id.content), "Sending", Snackbar.LENGTH_LONG)
+ .setAction("Action", null).show();
+ }
+
+ @Override
+ protected Void doInBackground(HashMap... params) {
+ HashMap emailContents = params[0];
+ String recipient = emailContents.get("RECIPIENT");
+ String subject = emailContents.get("SUBJECT");
+ String body = emailContents.get("BODY");
+ String sender = "me"; // stupid!!
+ try {
+ Message message = createMessageWithEmail(createEmail(recipient, sender, subject, body));
+
+ mService.users().messages().send(sender, message).execute();
+ Log.i("EMAIL", "Email sent to: " + recipient);
+ } catch (MessagingException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+
+ }
+ }
+
+ private class SaveDraftAsyncTask extends AsyncTask {
+ private com.google.api.services.gmail.Gmail mService = null;
+
+ public SaveDraftAsyncTask(GoogleAccountCredential credential) {
+ HttpTransport transport = AndroidHttp.newCompatibleTransport();
+ com.google.api.client.json.JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
+ mService = new com.google.api.services.gmail.Gmail.Builder(
+ transport, jsonFactory, credential)
+ .setApplicationName("Gmail API Android")
+ .build();
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ Toast.makeText(EmailItemListActivity.this, "Draft saved.", Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ protected Void doInBackground(HashMap... params) {
+ HashMap draftContents = params[0];
+ String subject = "";
+ String recipient = "";
+ String body = "";
+ String sender = "me";
+
+ //detect whether
+
+ if (draftContents.get("SUBJECT") != null) {
+ subject = draftContents.get("SUBJECT");
+ } else {
+ draftContents.put("SUBJECT", "");
+ }
+ if (draftContents.get("BODY") != null) {
+ body = draftContents.get("BODY");
+ } else {
+ draftContents.put("BODY", "");
+ }
+ if (draftContents.get("RECIPIENT") != null) {
+ recipient = draftContents.get("RECIPIENT");
+ } else {
+ draftContents.put("RECIPIENT", "");
+ }
+
+ try {
+ MimeMessage mimeMessage = createEmail(recipient, sender, subject, body);
+ Draft draft = createDraft(mService, sender, mimeMessage);
+ String draftId = draft.getId();
+ draftContents.put("ID", draftId);
+ mHelper.saveDraftToDb(draftContents);
+
+ } catch (MessagingException e) {
+ e.printStackTrace();
+ cancel(true);
+ } catch (IOException e) {
+ e.printStackTrace();
+ cancel(true);
+ }
+
+ return null;
+ }
+ }
+
+ private class SearchEmailAsyncTask extends AsyncTask> {
+
+ private String id;
+ private String snippet;
+ private String date;
+ private String subject;
+ private String sender;
+ HashMap searchHash;
+ List searchList;
+
+ HashMap emailHashFromDb;
+ List emailListFromDb;
+
+ public SearchEmailAsyncTask() {
+ searchHash = new HashMap<>();
+ searchList = new ArrayList<>();
+ emailHashFromDb = new HashMap<>();
+ emailListFromDb = new ArrayList<>();
+ }
+
+ @Override
+ protected List doInBackground(String... params) {
+ mHelper = MailDatabaseOpenHelper.getInstance(EmailItemListActivity.this);
+ String query = params[0];
+ Cursor searchCursor = mHelper.searchEmailDb(query);
+ searchCursor.moveToFirst();
+ while (!searchCursor.isAfterLast()) {
+ searchHash.clear();
+ sender = searchCursor.getString(searchCursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SENDER));
+ date = searchCursor.getString(searchCursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_DATE));
+ subject = searchCursor.getString(searchCursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SUBJECT));
+ id = searchCursor.getString(searchCursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_ID));
+ snippet = searchCursor.getString(searchCursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SNIPPET));
+
+ searchHash.put(MailDatabaseOpenHelper.MAIL_SENDER, sender);
+ searchHash.put(MailDatabaseOpenHelper.MAIL_SUBJECT, subject);
+ searchHash.put(MailDatabaseOpenHelper.MAIL_SNIPPET, snippet);
+ searchHash.put(MailDatabaseOpenHelper.MAIL_ID, id);
+ searchHash.put(MailDatabaseOpenHelper.MAIL_DATE, date);
+
+ searchList.add(new Email(searchHash));
+
+ searchCursor.moveToNext();
+
+ }
+
+ Cursor cursor = mHelper.getAllEmailsFromDb();
+ cursor.moveToFirst();
+ while (!cursor.isAfterLast()) {
+ emailHashFromDb.clear();
+ emailHashFromDb.put("SENDER", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SENDER)));
+ emailHashFromDb.put("DATE", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_DATE)));
+ emailHashFromDb.put("SUBJECT", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SUBJECT)));
+ emailHashFromDb.put("ID", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_ID)));
+ emailHashFromDb.put("SNIPPET", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_SNIPPET)));
+ emailHashFromDb.put("DRAFT", cursor.getString(cursor.getColumnIndex(MailDatabaseOpenHelper.MAIL_DRAFT)));
+ emailListFromDb.add(new Email(emailHashFromDb));
+ cursor.moveToNext();
+ }
+ searchCursor.close();
+ cursor.close();
+ mRecyclerViewList = emailListFromDb;
+ return searchList;
+ }
+
+ @Override
+ protected void onPostExecute(List emailList) {
+ mEmailRecyclerAdapter = new EmailRecyclerAdapter(EmailItemListActivity.this, mRecyclerViewList);
+ emaillistRecycler.setAdapter(mEmailRecyclerAdapter);
+ mEmailRecyclerAdapter.animateTo(emailList);
+ emaillistRecycler.scrollToPosition(0);
+
+ }
+ }
+
+
+ public static 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);
+ InternetAddress tAddress = new InternetAddress(to);
+ InternetAddress fAddress = new InternetAddress(from);
+
+ email.setFrom(new InternetAddress(from));
+ email.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
+ email.setSubject(subject);
+ email.setText(bodyText);
+ return email;
+ }
+
+ public static Message createMessageWithEmail(MimeMessage email) throws MessagingException, IOException {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ email.writeTo(bytes);
+ String encodedEmail = com.google.api.client.util.Base64.encodeBase64URLSafeString(bytes.toByteArray());
+ Message message = new Message();
+ message.setRaw(encodedEmail);
+ return message;
+ }
+
+ public static Draft createDraft(Gmail service, String userId, MimeMessage email) throws MessagingException, IOException {
+ Message message = createMessageWithEmail(email);
+ Draft draft = new Draft();
+ draft.setMessage(message);
+ draft = service.users().drafts().create(userId, draft).execute();
+
+ System.out.println("draft id:" + draft.getId());
+ return draft;
+
+ }
+
+ public void setRecyclerView(List recyclerList) {
+ mRecyclerViewList = recyclerList;
+
+ emaillistRecycler.setHasFixedSize(true);
+ emaillistRecycler.setLayoutManager(new LinearLayoutManager(EmailItemListActivity.this));
+ emaillistRecycler.addItemDecoration(new VerticalSpaceItemDecoration(20));
+ emaillistRecycler.addItemDecoration(new DividerItemDecoration(EmailItemListActivity.this, R.drawable.divider));
+ emailRecyclerAdapter = new EmailRecyclerAdapter(EmailItemListActivity.this, mRecyclerViewList);
+ emaillistRecycler.setAdapter(emailRecyclerAdapter);
+ }
+
+ public void saveDraft(HashMap draftMap) {
+ new SaveDraftAsyncTask(mCredential).execute(draftMap);
+ }
+
+
+ //For the case of backing in compose fragment
+
+ @Override
+ public void onBackPressed() {
+
+ int count = getSupportFragmentManager().getBackStackEntryCount();
+
+ if (count == 0) {
+ super.onBackPressed();
+
+ } else {
+ getSupportFragmentManager().popBackStack();
+ }
+ }
+
+
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/Fragments/ComposeFragment.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/Fragments/ComposeFragment.java
new file mode 100644
index 0000000..24d5f44
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/Fragments/ComposeFragment.java
@@ -0,0 +1,166 @@
+package com.adi.ho.jackie.emailapp.Fragments;
+
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.media.Image;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.adi.ho.jackie.emailapp.EmailItemListActivity;
+import com.adi.ho.jackie.emailapp.R;
+
+import java.util.HashMap;
+
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+
+/**
+ * A simple {@link Fragment} subclass.
+ */
+public class ComposeFragment extends DialogFragment {
+
+ EditText senderEditText;
+ EditText subjectEditText;
+ EditText bodyEditText;
+ ImageView exitComposeBut;
+ SendEmailTaskListener sendEmailTaskListener;
+ SaveDraftsListener saveDraftsListener;
+
+ public interface SendEmailTaskListener {
+ void sendEmail(HashMap hashMap);
+ }
+
+ public interface SaveDraftsListener {
+ void saveDraft(HashMap hashMap);
+ }
+
+ public ComposeFragment() {
+ // Required empty public constructor
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ sendEmailTaskListener = (SendEmailTaskListener) activity;
+ saveDraftsListener = (SaveDraftsListener)activity;
+ } catch (ClassCastException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_main, container, false);
+ senderEditText = (EditText) view.findViewById(R.id.compose_sendto_edit);
+ subjectEditText = (EditText) view.findViewById(R.id.composesubject_edit);
+ bodyEditText = (EditText) view.findViewById(R.id.composeemail_body_edit);
+ exitComposeBut = (ImageView) view.findViewById(R.id.exit_compose_button);
+ getDialog().setCanceledOnTouchOutside(true);
+ return view;
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ Button sendEmailButton = (Button) view.findViewById(R.id.composeemail_send_button);
+ sendEmailButton.setOnClickListener(sendEmailListener);
+ exitComposeBut.setOnClickListener(exitListener);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Dialog dialog = super.onCreateDialog(savedInstanceState);
+ dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+ return dialog;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ getDialog().getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
+ }
+
+ View.OnClickListener sendEmailListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ String sendingEmailTo = senderEditText.getText().toString();
+ String sendingSubject = subjectEditText.getText().toString();
+ String emailBody = bodyEditText.getText().toString();
+
+
+ if (!isValidEmailAddress(sendingEmailTo)) {
+ senderEditText.setError("Valid email required");
+ return;
+ }
+ if (sendingSubject.trim().isEmpty()) {
+ subjectEditText.setError("Subject required");
+ return;
+ }
+
+
+ HashMap emailContents = new HashMap<>();
+ emailContents.put("SUBJECT", sendingSubject);
+ emailContents.put("RECIPIENT", sendingEmailTo);
+ emailContents.put("BODY", emailBody);
+
+ sendEmailTaskListener.sendEmail(emailContents);
+ getDialog().dismiss();
+ }
+ };
+
+ View.OnClickListener exitListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ HashMap savingDraft = new HashMap<>();
+
+ if (bodyEditText.getText().toString().trim().isEmpty() && senderEditText.getText().toString().trim().isEmpty() && subjectEditText.getText().toString().trim().isEmpty()){
+ getDialog().dismiss();
+ } else {
+ if (!subjectEditText.getText().toString().isEmpty()) {
+ savingDraft.put("SUBJECT", subjectEditText.getText().toString());
+ }
+ if (!senderEditText.getText().toString().isEmpty()){
+ savingDraft.put("RECIPIENT", senderEditText.getText().toString());
+ }
+ if (!bodyEditText.getText().toString().isEmpty()){
+ savingDraft.put("BODY", senderEditText.getText().toString());
+ }
+
+ saveDraftsListener.saveDraft(savingDraft);
+ }
+
+ getDialog().dismiss();
+ }
+ };
+
+
+
+
+
+ public static boolean isValidEmailAddress(String email) {
+ boolean result = true;
+ try {
+ InternetAddress emailAddr = new InternetAddress(email);
+ emailAddr.validate();
+ } catch (AddressException ex) {
+ result = false;
+ }
+ return result;
+ }
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/MainActivity.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/MainActivity.java
new file mode 100644
index 0000000..4ba5e70
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/MainActivity.java
@@ -0,0 +1,282 @@
+//package com.adi.ho.jackie.emailapp;
+//
+//import android.accounts.AccountManager;
+//import android.app.Dialog;
+//import android.app.ProgressDialog;
+//import android.content.Context;
+//import android.content.Intent;
+//import android.content.SharedPreferences;
+//import android.net.ConnectivityManager;
+//import android.net.NetworkInfo;
+//import android.os.AsyncTask;
+//import android.os.Bundle;
+//import android.support.design.widget.FloatingActionButton;
+//import android.support.design.widget.Snackbar;
+//import android.support.v7.app.AppCompatActivity;
+//import android.support.v7.widget.Toolbar;
+//import android.view.View;
+//import android.view.Menu;
+//import android.view.MenuItem;
+//import android.widget.Toast;
+//
+//import com.fasterxml.jackson.core.JsonFactory;
+//import com.google.android.gms.common.ConnectionResult;
+//import com.google.android.gms.common.GooglePlayServicesUtil;
+//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.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
+//import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
+//import com.google.api.client.http.HttpTransport;
+//import com.google.api.client.json.jackson2.JacksonFactory;
+//import com.google.api.client.util.ExponentialBackOff;
+//import com.google.api.services.gmail.GmailScopes;
+//import com.google.api.services.gmail.model.Label;
+//import com.google.api.services.gmail.model.ListLabelsResponse;
+//
+//import java.io.IOException;
+//import java.util.ArrayList;
+//import java.util.Arrays;
+//import java.util.List;
+//
+//public class MainActivity extends AppCompatActivity {
+// GoogleAccountCredential mCredential;
+// ProgressDialog mProgress;
+//
+// static final int REQUEST_ACCOUNT_PICKER = 1000;
+// static final int REQUEST_AUTHORIZATION = 1001;
+// static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
+// private static final String PREF_ACCOUNT_NAME = "accountName";
+// private static final String[] SCOPES = { GmailScopes.GMAIL_LABELS };
+//
+// @Override
+// protected void onCreate(Bundle savedInstanceState) {
+// super.onCreate(savedInstanceState);
+// mProgress = new ProgressDialog(this);
+// mProgress.setMessage("Calling Gmail API ...");
+// setContentView(R.layout.activity_main);
+//
+//
+// // Initialize credentials and service object.
+// SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
+// mCredential = GoogleAccountCredential.usingOAuth2(
+// getApplicationContext(), Arrays.asList(SCOPES))
+// .setBackOff(new ExponentialBackOff())
+// .setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
+//
+//
+//
+//
+// Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+// setSupportActionBar(toolbar);
+//
+// FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+// fab.setOnClickListener(new View.OnClickListener() {
+// @Override
+// public void onClick(View view) {
+// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
+// .setAction("Action", null).show();
+// }
+// });
+// }
+//
+// @Override
+// public boolean onCreateOptionsMenu(Menu menu) {
+// // Inflate the menu; this adds items to the action bar if it is present.
+// getMenuInflater().inflate(R.menu.menu_main, menu);
+// return true;
+// }
+//
+// @Override
+// public boolean onOptionsItemSelected(MenuItem item) {
+// // Handle action bar item clicks here. The action bar will
+// // automatically handle clicks on the Home/Up button, so long
+// // as you specify a parent activity in AndroidManifest.xml.
+// int id = item.getItemId();
+//
+// //noinspection SimplifiableIfStatement
+// if (id == R.id.action_settings) {
+// return true;
+// }
+//
+// return super.onOptionsItemSelected(item);
+// }
+//
+// @Override
+// protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+// super.onActivityResult(requestCode, resultCode, data);
+// switch(requestCode) {
+// case REQUEST_GOOGLE_PLAY_SERVICES:
+// if (resultCode != RESULT_OK) {
+// isGooglePlayServicesAvailable();
+// }
+// break;
+// case REQUEST_ACCOUNT_PICKER:
+// if (resultCode == RESULT_OK && data != null &&
+// data.getExtras() != null) {
+// String accountName =
+// data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
+// if (accountName != null) {
+// mCredential.setSelectedAccountName(accountName);
+// SharedPreferences settings =
+// getPreferences(Context.MODE_PRIVATE);
+// SharedPreferences.Editor editor = settings.edit();
+// editor.putString(PREF_ACCOUNT_NAME, accountName);
+// editor.apply();
+// }
+// } else if (resultCode == RESULT_CANCELED) {
+// Toast.makeText(MainActivity.this, "Account unspecified", Toast.LENGTH_SHORT).show();
+// }
+// break;
+// case REQUEST_AUTHORIZATION:
+// if (resultCode != RESULT_OK) {
+// chooseAccount();
+// }
+// break;
+// }
+//
+// super.onActivityResult(requestCode, resultCode, data);
+// }
+// private void refreshResults() {
+// if (mCredential.getSelectedAccountName() == null) {
+// chooseAccount();
+// } else {
+// if (isDeviceOnline()) {
+// new MakeRequestTask(mCredential).execute();
+// } else {
+// Toast.makeText(MainActivity.this, "No network connection", Toast.LENGTH_SHORT).show();
+// }
+// }
+// }
+//
+// private void chooseAccount() {
+// startActivityForResult(
+// mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
+// }
+// private boolean isDeviceOnline() {
+// ConnectivityManager connMgr =
+// (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+// NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
+// return (networkInfo != null && networkInfo.isConnected());
+// }
+//
+// @Override
+// protected void onResume() {
+// super.onResume();
+// if (isGooglePlayServicesAvailable()) {
+// refreshResults();
+// }
+// }
+// private boolean isGooglePlayServicesAvailable() {
+// final int connectionStatusCode =
+// GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
+// if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
+// showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
+// return false;
+// } else if (connectionStatusCode != ConnectionResult.SUCCESS ) {
+// return false;
+// }
+// return true;
+// }
+// /**
+// * Display an error dialog showing that Google Play Services is missing
+// * or out of date.
+// * @param connectionStatusCode code describing the presence (or lack of)
+// * Google Play Services on this device.
+// */
+// void showGooglePlayServicesAvailabilityErrorDialog(
+// final int connectionStatusCode) {
+// Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
+// connectionStatusCode,
+// MainActivity.this,
+// REQUEST_GOOGLE_PLAY_SERVICES);
+// dialog.show();
+// }
+// /**
+// * An asynchronous task that handles the Gmail API call.
+// * Placing the API calls in their own task ensures the UI stays responsive.
+// */
+// private class MakeRequestTask extends AsyncTask> {
+// private com.google.api.services.gmail.Gmail mService = null;
+// private Exception mLastError = null;
+//
+// public MakeRequestTask(GoogleAccountCredential credential) {
+// HttpTransport transport = AndroidHttp.newCompatibleTransport();
+// com.google.api.client.json.JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
+// mService = new com.google.api.services.gmail.Gmail.Builder(
+// transport, jsonFactory, credential)
+// .setApplicationName("Gmail API Android Quickstart")
+// .build();
+// }
+//
+// /**
+// * Background task to call Gmail API.
+// * @param params no parameters needed for this task.
+// */
+// @Override
+// protected List doInBackground(Void... params) {
+// try {
+// return getDataFromApi();
+// } catch (Exception e) {
+// mLastError = e;
+// cancel(true);
+// return null;
+// }
+// }
+//
+// /**
+// * Fetch a list of Gmail labels attached to the specified account.
+// * @return List of Strings labels.
+// * @throws IOException
+// */
+// private List getDataFromApi() throws IOException {
+// // Get the labels in the user's account.
+// String user = "me";
+// List labels = new ArrayList<>();
+// ListLabelsResponse listResponse =
+// mService.users().labels().list(user).execute();
+// for (Label label : listResponse.getLabels()) {
+// labels.add(label.getName());
+// }
+// return labels;
+// }
+//
+//
+// @Override
+// protected void onPreExecute() {
+// // mOutputText.setText("");
+// mProgress.show();
+// }
+//
+// @Override
+// protected void onPostExecute(List output) {
+// mProgress.hide();
+// if (output == null || output.size() == 0) {
+// // mOutputText.setText("No results returned.");
+// } else {
+// output.add(0, "Data retrieved using the Gmail API:");
+// //mOutputText.setText(TextUtils.join("\n", output));
+// }
+// }
+//
+// @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(),
+// MainActivity.REQUEST_AUTHORIZATION);
+// } else {
+// // mOutputText.setText("The following error occurred:\n"
+//// + mLastError.getMessage());
+// }
+// } else {
+// // mOutputText.setText("Request cancelled.");
+// }
+// }
+// }
+//}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/database/MailDatabaseOpenHelper.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/database/MailDatabaseOpenHelper.java
new file mode 100644
index 0000000..5112e45
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/database/MailDatabaseOpenHelper.java
@@ -0,0 +1,143 @@
+package com.adi.ho.jackie.emailapp.database;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import com.adi.ho.jackie.emailapp.Email;
+
+import java.util.HashMap;
+
+/**
+ * Created by JHADI on 2/26/16.
+ */
+public class MailDatabaseOpenHelper extends SQLiteOpenHelper {
+
+ private static final String DATABASE_NAME = "MAILEMAILS";
+ private static final int DATABASE_VERSION = 1;
+ private static final String MAIL_EMAIL_TABLE = "EMAILS";
+ private static final String DRAFT_EMAIL_TABLE = "DRAFTS";
+ public static final String MAIL_ID = "ID";
+ public static final String MAIL_DATE = "DATE";
+ public static final String MAIL_BODY = "BODY";
+ public static final String MAIL_RECIPIENT = "RECIPIENT";
+ public static final String MAIL_SENDER = "SENDER";
+ public static final String MAIL_SNIPPET = "SNIPPET";
+ public static final String MAIL_DRAFT = "DRAFT";
+ public static final String MAIL_SUBJECT = "SUBJECT";
+ private static final String[] MAIL_COLUMNS = {MAIL_ID, MAIL_SENDER, MAIL_RECIPIENT, MAIL_DATE, MAIL_SNIPPET, MAIL_DRAFT, MAIL_SUBJECT, MAIL_BODY};
+ private static final String[] MAIL_COLUMNS_LISTACT = {MAIL_ID, MAIL_SENDER, MAIL_DATE, MAIL_SNIPPET, MAIL_DRAFT, MAIL_SUBJECT};
+
+ public static final String DRAFT_ID = "ID";
+ public static final String DRAFT_RECIPIENT = "RECIPIENT";
+ public static final String DRAFT_SUBJECT = "SUBJECT";
+ public static final String DRAFT_BODY = "BODY";
+ private static final String[] DRAFT_COLUMNS = {DRAFT_ID, DRAFT_RECIPIENT, DRAFT_SUBJECT, DRAFT_BODY};
+
+
+ private Context context;
+ private static MailDatabaseOpenHelper instance;
+ private SQLiteDatabase mDatabase;
+
+ private MailDatabaseOpenHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ this.context = context;
+ mDatabase = getWritableDatabase();
+ }
+
+ public static MailDatabaseOpenHelper getInstance(Context context) {
+ if (instance == null) {
+ instance = new MailDatabaseOpenHelper(context);
+ }
+ return instance;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + MAIL_EMAIL_TABLE + " ("
+ + MAIL_ID + " TEXT PRIMARY KEY, " +
+ MAIL_SENDER + " TEXT, " +
+ MAIL_RECIPIENT + " TEXT, " +
+ MAIL_DATE + " TEXT, " +
+ MAIL_SNIPPET + " TEXT, " +
+ MAIL_DRAFT + " TEXT, " +
+ MAIL_SUBJECT + " TEXT, " +
+ MAIL_BODY + " TEXT)");
+ db.execSQL("CREATE TABLE " + DRAFT_EMAIL_TABLE + " ("
+ + DRAFT_ID + " TEXT PRIMARY KEY, " +
+ DRAFT_RECIPIENT + " TEXT, " +
+ DRAFT_SUBJECT + " TEXT, " +
+ DRAFT_BODY + " TEXT) ");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ db.execSQL("DROP TABLE IF EXIST " + MAIL_EMAIL_TABLE);
+ db.execSQL("DROP TABLE IF EXIST " + DRAFT_EMAIL_TABLE);
+ onCreate(db);
+ }
+
+ public void addEmailsToDatabase(Email email) {
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(MAIL_ID, email.getId());
+ contentValues.put(MAIL_RECIPIENT, email.getRecipient());
+ contentValues.put(MAIL_SENDER, email.getSender());
+ contentValues.put(MAIL_DATE, email.getDate());
+ contentValues.put(MAIL_SNIPPET, email.getSnippet());
+ contentValues.put(MAIL_DRAFT, email.getFavorite());
+ contentValues.put(MAIL_BODY, email.getBody());
+ contentValues.put(MAIL_SUBJECT, email.getSubject());
+ if (!mDatabase.query(MAIL_EMAIL_TABLE, MAIL_COLUMNS, MAIL_ID + " = ? ", new String[]{email.getId()}, null, null, null, null).moveToFirst()) {
+ Log.d("DATABASE", "Inserting in to db, id: " + email.getId());
+ mDatabase.insert(MAIL_EMAIL_TABLE, null, contentValues);
+ }
+
+ }
+
+ public Cursor getEmailById(String id) {
+
+ Cursor cursor = mDatabase.query(MAIL_EMAIL_TABLE, MAIL_COLUMNS, MAIL_ID + " = ? ",
+ new String[]{id}, null, null, null, null);
+ return cursor;
+ }
+
+ public Cursor getAllEmailsFromDb() {
+
+ Cursor cursor = mDatabase.query(MAIL_EMAIL_TABLE, MAIL_COLUMNS_LISTACT, null, null, null, null, null);
+ return cursor;
+
+ }
+
+ public void saveDraftToDb(HashMap draftMap) {
+ ContentValues values = new ContentValues();
+ String emailDraftId = draftMap.get("ID");
+ String draftSubject = draftMap.get("SUBJECT");
+ String draftRecipient = draftMap.get("RECIPIENT");
+ String draftBody = draftMap.get("BODY");
+ values.put(DRAFT_ID, emailDraftId);
+ values.put(DRAFT_BODY, draftBody);
+ values.put(DRAFT_RECIPIENT, draftRecipient);
+ values.put(DRAFT_SUBJECT, draftSubject);
+
+ mDatabase.insert(DRAFT_EMAIL_TABLE, null, values);
+ }
+
+ public Cursor retrieveDraftsFromDb() {
+ return mDatabase.query(DRAFT_EMAIL_TABLE, DRAFT_COLUMNS, null, null, null, null, null);
+ }
+
+ public Cursor searchEmailDb(String query) {
+ Cursor cursor = mDatabase.query(MAIL_EMAIL_TABLE, MAIL_COLUMNS, MAIL_RECIPIENT + " LIKE ? OR " +
+ MAIL_SENDER + " LIKE ? OR " + MAIL_SUBJECT + " LIKE ? OR " + MAIL_BODY + " LIKE ? ",
+ new String[]{"%" + query + "%", "%" + query + "%", "%" + query + "%", "%" + query + "%"}, null, null, null);
+ return cursor;
+ }
+ public void clearDb(){
+// mDatabase.execSQL("DROP TABLE IF EXIST " +MAIL_EMAIL_TABLE);
+ mDatabase.delete(MAIL_EMAIL_TABLE,null,null);
+ }
+
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/DividerItemDecoration.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/DividerItemDecoration.java
new file mode 100644
index 0000000..af7b73b
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/DividerItemDecoration.java
@@ -0,0 +1,54 @@
+package com.adi.ho.jackie.emailapp.recyclerlistitems;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+/**
+ * Created by JHADI on 2/28/16.
+ */
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+
+ private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
+
+ private Drawable mDivider;
+
+ /**
+ * Default divider
+ */
+ public DividerItemDecoration(Context context) {
+ final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
+ mDivider = styledAttributes.getDrawable(0);
+ styledAttributes.recycle();
+ }
+
+ /**
+ * Custom divider
+ */
+ public DividerItemDecoration(Context context, int resId) {
+ mDivider = ContextCompat.getDrawable(context, resId);
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ int left = parent.getPaddingLeft();
+ int right = parent.getWidth() - parent.getPaddingRight();
+
+ int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = parent.getChildAt(i);
+
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+
+ int top = child.getBottom() + params.bottomMargin;
+ int bottom = top + mDivider.getIntrinsicHeight();
+
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/EmailRecyclerAdapter.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/EmailRecyclerAdapter.java
new file mode 100644
index 0000000..c47ca15
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/EmailRecyclerAdapter.java
@@ -0,0 +1,110 @@
+package com.adi.ho.jackie.emailapp.recyclerlistitems;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.adi.ho.jackie.emailapp.Email;
+import com.adi.ho.jackie.emailapp.EmailItemDetailActivity;
+import com.adi.ho.jackie.emailapp.EmailItemDetailFragment;
+import com.adi.ho.jackie.emailapp.R;
+
+import java.util.List;
+
+/**
+ * Created by JHADI on 2/25/16.
+ */
+public class EmailRecyclerAdapter extends RecyclerView.Adapter {
+
+ private Context context;
+ private List emailList;
+ private FragmentManager fragmentManager;
+
+ public EmailRecyclerAdapter(Context context, List emailList) {
+ this.context = context;
+ this.emailList = emailList;
+ }
+
+ @Override
+ public EmailViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.email_layout, null);
+ EmailViewHolder evh = new EmailViewHolder(view);
+ return evh;
+ }
+
+ @Override
+ public void onBindViewHolder(EmailViewHolder holder, final int position) {
+ holder.emailDate.setText(emailList.get(position).getDate());
+ holder.emailLabel.setText(emailList.get(position).getSender());
+ holder.emailSnippet.setText(emailList.get(position).getSnippet());
+ holder.emailId.setText(emailList.get(position).getId());
+ holder.emailSubject.setText(emailList.get(position).getSubject());
+
+ }
+
+ @Override
+ public int getItemCount() {
+ return emailList.size();
+ }
+
+ //Methods for animating removing and adding items
+ public Email removeItem(int position) {
+ final Email email = emailList.remove(position);
+ notifyItemRemoved(position);
+ return email;
+ }
+
+ public void addItem(int position, Email email) {
+ emailList.add(position, email);
+ notifyItemInserted(position);
+ }
+
+ public void moveItem(int fromPosition, int toPosition) {
+ final Email email = emailList.remove(fromPosition);
+ emailList.add(toPosition, email);
+ notifyItemMoved(fromPosition, toPosition);
+ }
+
+ public void animateTo(List emails) {
+ applyAndAnimateRemovals(emails);
+ applyAndAnimateAdditions(emails);
+ applyAndAnimateMovedItems(emails);
+ }
+
+ private void applyAndAnimateRemovals(List emails) {
+ for (int i = emailList.size() - 1; i >= 0; i--) {
+ final Email email = emailList.get(i);
+ if (!emails.contains(email)) {
+ removeItem(i);
+ }
+ }
+ }
+
+ private void applyAndAnimateAdditions(List emails) {
+ for (int i = 0, count = emails.size(); i < count; i++) {
+ final Email email = emails.get(i);
+ if (!emailList.contains(email)) {
+ addItem(i, email);
+ }
+ }
+ }
+
+ private void applyAndAnimateMovedItems(List emails) {
+ for (int toPosition = emails.size() - 1; toPosition >= 0; toPosition--) {
+ final Email email = emails.get(toPosition);
+ final int fromPosition = emailList.indexOf(email);
+ if (fromPosition >= 0 && fromPosition != toPosition) {
+ moveItem(fromPosition, toPosition);
+ }
+ }
+ }
+
+
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/EmailViewHolder.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/EmailViewHolder.java
new file mode 100644
index 0000000..009741b
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/EmailViewHolder.java
@@ -0,0 +1,73 @@
+package com.adi.ho.jackie.emailapp.recyclerlistitems;
+
+import android.app.Activity;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.adi.ho.jackie.emailapp.EmailItemDetailActivity;
+import com.adi.ho.jackie.emailapp.EmailItemDetailFragment;
+import com.adi.ho.jackie.emailapp.R;
+
+/**
+ * Created by JHADI on 2/25/16.
+ */
+public class EmailViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
+
+ private MakeSecondFragmentListener mFragmentListener;
+
+ public interface MakeSecondFragmentListener {
+ public void makeSecondFragment(String emailId);
+ }
+
+ TextView emailLabel;
+ ImageView emailPic;
+ TextView emailDate;
+ ImageView emailStar;
+ TextView emailSnippet;
+ TextView emailId;
+ TextView emailSubject;
+ RelativeLayout emailLayout;
+ private Context context;
+
+ public EmailViewHolder(View itemView) {
+ super(itemView);
+ context = itemView.getContext();
+ // this.fragmentManager = fragmentManager;
+ itemView.setOnClickListener(this);
+
+ emailLabel = (TextView) itemView.findViewById(R.id.email_label);
+ emailDate = (TextView)itemView.findViewById(R.id.email_date);
+ emailSnippet = (TextView)itemView.findViewById(R.id.email_snippet);
+ emailId = (TextView)itemView.findViewById(R.id.invisible_id);
+ emailSubject = (TextView)itemView.findViewById(R.id.email_subject);
+ emailLayout = (RelativeLayout)itemView.findViewById(R.id.email_layout_container);
+ }
+
+ @Override
+ public void onClick(View v) {
+ Activity activity = (Activity)context;
+ String id = emailId.getText().toString();
+ if (activity.findViewById(R.id.emailitem_detail_container) != null){
+
+ try {
+ mFragmentListener = (MakeSecondFragmentListener)activity;
+ mFragmentListener.makeSecondFragment(id);
+ } catch (ClassCastException e){
+ e.printStackTrace();
+ }
+
+
+ } else {
+ Intent intent = new Intent(context, EmailItemDetailActivity.class);
+ intent.putExtra("EMAILID", id);
+ context.startActivity(intent);
+ }
+ }
+}
diff --git a/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/VerticalSpaceItemDecoration.java b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/VerticalSpaceItemDecoration.java
new file mode 100644
index 0000000..7a4b1b8
--- /dev/null
+++ b/MyApplication2/app/src/main/java/com/adi/ho/jackie/emailapp/recyclerlistitems/VerticalSpaceItemDecoration.java
@@ -0,0 +1,25 @@
+package com.adi.ho.jackie.emailapp.recyclerlistitems;
+
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+/**
+ * Created by JHADI on 2/26/16.
+ */
+public class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration {
+
+ private final int mVerticalSpaceHeight;
+
+ public VerticalSpaceItemDecoration(int mVerticalSpaceHeight) {
+ this.mVerticalSpaceHeight = mVerticalSpaceHeight;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
+ RecyclerView.State state) {
+ outRect.bottom = mVerticalSpaceHeight;
+ outRect.right = 20;
+ outRect.left = 20;
+ }
+}
\ No newline at end of file
diff --git a/MyApplication2/app/src/main/res/drawable/border.xml b/MyApplication2/app/src/main/res/drawable/border.xml
new file mode 100644
index 0000000..448ea88
--- /dev/null
+++ b/MyApplication2/app/src/main/res/drawable/border.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/app/src/main/res/drawable/divider.xml b/MyApplication2/app/src/main/res/drawable/divider.xml
new file mode 100644
index 0000000..139cefa
--- /dev/null
+++ b/MyApplication2/app/src/main/res/drawable/divider.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/app/src/main/res/drawable/refresh.png b/MyApplication2/app/src/main/res/drawable/refresh.png
new file mode 100644
index 0000000..728fb3a
Binary files /dev/null and b/MyApplication2/app/src/main/res/drawable/refresh.png differ
diff --git a/MyApplication2/app/src/main/res/layout-land/emailitem_list.xml b/MyApplication2/app/src/main/res/layout-land/emailitem_list.xml
new file mode 100644
index 0000000..52fc367
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout-land/emailitem_list.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/layout-w900dp/emailitem_list.xml b/MyApplication2/app/src/main/res/layout-w900dp/emailitem_list.xml
new file mode 100644
index 0000000..62c37e5
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout-w900dp/emailitem_list.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/layout/activity_emailitem_detail.xml b/MyApplication2/app/src/main/res/layout/activity_emailitem_detail.xml
new file mode 100644
index 0000000..a4594db
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/activity_emailitem_detail.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/layout/activity_emailitem_list.xml b/MyApplication2/app/src/main/res/layout/activity_emailitem_list.xml
new file mode 100644
index 0000000..a105c64
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/activity_emailitem_list.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/layout/activity_main.xml b/MyApplication2/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..fd99205
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/layout/content_main.xml b/MyApplication2/app/src/main/res/layout/content_main.xml
new file mode 100644
index 0000000..31806be
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/content_main.xml
@@ -0,0 +1,9 @@
+
diff --git a/MyApplication2/app/src/main/res/layout/email_layout.xml b/MyApplication2/app/src/main/res/layout/email_layout.xml
new file mode 100644
index 0000000..7be4507
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/email_layout.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/app/src/main/res/layout/emailitem_detail.xml b/MyApplication2/app/src/main/res/layout/emailitem_detail.xml
new file mode 100644
index 0000000..8a5c6f8
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/emailitem_detail.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/layout/emailitem_list.xml b/MyApplication2/app/src/main/res/layout/emailitem_list.xml
new file mode 100644
index 0000000..1bec7cd
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/emailitem_list.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/layout/emailitem_list_content.xml b/MyApplication2/app/src/main/res/layout/emailitem_list_content.xml
new file mode 100644
index 0000000..3df9ca7
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/emailitem_list_content.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/app/src/main/res/layout/fragment_main.xml b/MyApplication2/app/src/main/res/layout/fragment_main.xml
new file mode 100644
index 0000000..5b76107
--- /dev/null
+++ b/MyApplication2/app/src/main/res/layout/fragment_main.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/menu/menu_main.xml b/MyApplication2/app/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..4f3329a
--- /dev/null
+++ b/MyApplication2/app/src/main/res/menu/menu_main.xml
@@ -0,0 +1,25 @@
+
diff --git a/MyApplication2/app/src/main/res/mipmap-hdpi/ic_launcher.png b/MyApplication2/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/MyApplication2/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/MyApplication2/app/src/main/res/mipmap-mdpi/ic_launcher.png b/MyApplication2/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/MyApplication2/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/MyApplication2/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/MyApplication2/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/MyApplication2/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/MyApplication2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/MyApplication2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/MyApplication2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/MyApplication2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/MyApplication2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
Binary files /dev/null and b/MyApplication2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/MyApplication2/app/src/main/res/values-v21/styles.xml b/MyApplication2/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..251fb9f
--- /dev/null
+++ b/MyApplication2/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,9 @@
+>
+
+
+
diff --git a/MyApplication2/app/src/main/res/values-w820dp/dimens.xml b/MyApplication2/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/MyApplication2/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/MyApplication2/app/src/main/res/values/colors.xml b/MyApplication2/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..3ab3e9c
--- /dev/null
+++ b/MyApplication2/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/MyApplication2/app/src/main/res/values/dimens.xml b/MyApplication2/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..3aca65d
--- /dev/null
+++ b/MyApplication2/app/src/main/res/values/dimens.xml
@@ -0,0 +1,9 @@
+
+
+ 16dp
+ 16dp
+ 16dp
+ 200dp
+ 200dp
+ 16dp
+
diff --git a/MyApplication2/app/src/main/res/values/strings.xml b/MyApplication2/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..5e5600c
--- /dev/null
+++ b/MyApplication2/app/src/main/res/values/strings.xml
@@ -0,0 +1,13 @@
+
+ EmailApp
+ Settings
+
+
+ Logout from Google
+ Revoke Access
+ EmailItems
+ EmailItem Detail
+
+
+ Hello blank fragment
+
diff --git a/MyApplication2/app/src/main/res/values/styles.xml b/MyApplication2/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..545b9c6
--- /dev/null
+++ b/MyApplication2/app/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyApplication2/app/src/main/res/xml/searchable.xml b/MyApplication2/app/src/main/res/xml/searchable.xml
new file mode 100644
index 0000000..a4f8fa7
--- /dev/null
+++ b/MyApplication2/app/src/main/res/xml/searchable.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/MyApplication2/app/src/test/java/com/adi/ho/jackie/emailapp/ExampleUnitTest.java b/MyApplication2/app/src/test/java/com/adi/ho/jackie/emailapp/ExampleUnitTest.java
new file mode 100644
index 0000000..6af6916
--- /dev/null
+++ b/MyApplication2/app/src/test/java/com/adi/ho/jackie/emailapp/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.adi.ho.jackie.emailapp;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/MyApplication2/build.gradle b/MyApplication2/build.gradle
new file mode 100644
index 0000000..e0b366a
--- /dev/null
+++ b/MyApplication2/build.gradle
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.5.0'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/MyApplication2/gradle.properties b/MyApplication2/gradle.properties
new file mode 100644
index 0000000..1d3591c
--- /dev/null
+++ b/MyApplication2/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/MyApplication2/gradle/wrapper/gradle-wrapper.jar b/MyApplication2/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..05ef575
Binary files /dev/null and b/MyApplication2/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/MyApplication2/gradle/wrapper/gradle-wrapper.properties b/MyApplication2/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..f23df6e
--- /dev/null
+++ b/MyApplication2/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Oct 21 11:34:03 PDT 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
diff --git a/MyApplication2/gradlew b/MyApplication2/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/MyApplication2/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/MyApplication2/gradlew.bat b/MyApplication2/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/MyApplication2/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/MyApplication2/settings.gradle b/MyApplication2/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/MyApplication2/settings.gradle
@@ -0,0 +1 @@
+include ':app'