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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +