diff --git a/README.md b/README.md index 0bf9d04..63a5514 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Espresso Android App ![icon](https://github.com/TonnyL/Espresso/blob/master/mobile/src/main/res/mipmap-xxxhdpi/ic_launcher.png) -Espresso is an express delivery tracking app designed with Material Design style, built on MVP(Model-View-Presenter) architecture with RxJava2, Retrofit2 and Realm database. +Espresso is an express delivery tracking app designed with Material Design style, built on MVP(Model-View-Presenter) architecture with RxJava2, Retrofit2, Realm database and ZXing. The source code in this repository reflects the app which supports mobile devices running Android 5.0+. @@ -18,9 +18,9 @@ With this app, you can: + Send feedback on using experience from your devices. ### Screenshots -![screenshot0](http://upload-images.jianshu.io/upload_images/2440049-649b96f3b8858cce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![screenshot0](https://github.com/TonnyL/Espresso/blob/master/art/screenshot0.png) -![screenshot1](http://upload-images.jianshu.io/upload_images/2440049-d3c50d9e5ca6f0a4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![screenshot1](https://github.com/TonnyL/Espresso/blob/master/art/screenshot1.png) ### How to Work with the Source I hope the source code for this app is useful for you as a reference or starting point for creating your own app. Here is some instructions to help you better build and run the code in Android Studio. @@ -48,9 +48,9 @@ This project is still in progress. Here are the some features that I will finish - [x] Launcher app widgets. - [x] App Shortcuts on devices that running Android 7.1+. - [x] Material design app onboarding pages. -- [ ] Chrome Custom Tabs. +- [x] Chrome Custom Tabs. - [x] Alphabet indexing for companies list. -- [ ] Search packages and companies. +- [x] Search packages and companies. - [ ] Day and night mode. - [x] Service to build notifications. - [x] Settings and about page. diff --git a/art/screenshot0.png b/art/screenshot0.png new file mode 100644 index 0000000..3441b1b Binary files /dev/null and b/art/screenshot0.png differ diff --git a/art/screenshot1.png b/art/screenshot1.png new file mode 100644 index 0000000..ec24788 Binary files /dev/null and b/art/screenshot1.png differ diff --git a/mobile/build.gradle b/mobile/build.gradle index a5bb50e..5f7ef61 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -38,25 +38,26 @@ dependencies { }) wearApp project(':wear') // Google Mobile Service - // Support libraries - // ReactiveX series - // Retrofit series - // Zxing - // Material data time picker - // CircleImageView compile 'com.google.android.gms:play-services:10.2.1' + // Support libraries compile 'com.android.support:appcompat-v7:25.3.0' compile 'com.android.support:support-v4:25.3.0' compile 'com.android.support:design:25.3.0' compile 'com.android.support:cardview-v7:25.3.0' compile 'com.android.support:preference-v14:25.3.0' + compile 'com.android.support:customtabs:25.3.0' + // ReactiveX series compile 'io.reactivex.rxjava2:rxjava:2.0.1' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' + // Retrofit series compile 'com.squareup.retrofit2:retrofit:2.2.0' compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' compile 'com.squareup.retrofit2:converter-gson:2.2.0' + // Zxing compile 'com.google.zxing:core:3.3.0' + // Material date time picker compile 'com.wdullaer:materialdatetimepicker:3.1.3' + // CircleImageView compile 'de.hdodenhof:circleimageview:2.1.0' testCompile 'junit:junit:4.12' } diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml index 2394ea9..d53c6a0 100644 --- a/mobile/src/main/AndroidManifest.xml +++ b/mobile/src/main/AndroidManifest.xml @@ -3,10 +3,18 @@ package="io.github.marktony.espresso"> + + + > searchCompanies(@NonNull String keyWords) { List results = rlm.copyFromRealm( rlm.where(Company.class) .like("name","*" + keyWords + "*", Case.INSENSITIVE) - /*.contains("tel", "*" + keyWords + "*") - .contains("website", "*" + keyWords + "*") - .contains("alphabet", "*" + keyWords + "*")*/ - .findAll()); + .or() + .like("tel", "*" + keyWords + "*", Case.INSENSITIVE) + .or() + .like("website", "*" + keyWords + "*", Case.INSENSITIVE) + .or() + .like("alphabet", "*" + keyWords + "*", Case.INSENSITIVE) + .findAllSorted("alphabet", Sort.ASCENDING)); return Observable.fromIterable(results) .toList() .toObservable(); diff --git a/mobile/src/main/java/io/github/marktony/espresso/data/source/local/PackagesLocalDataSource.java b/mobile/src/main/java/io/github/marktony/espresso/data/source/local/PackagesLocalDataSource.java index 70dd80a..c04bb30 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/data/source/local/PackagesLocalDataSource.java +++ b/mobile/src/main/java/io/github/marktony/espresso/data/source/local/PackagesLocalDataSource.java @@ -194,9 +194,13 @@ public Observable> searchPackages(@NonNull String keyWords) { Realm rlm = RealmHelper.newRealmInstance(); return Observable.fromIterable(rlm.copyFromRealm( rlm.where(Package.class) + .like("name", "*" + keyWords + "*", Case.INSENSITIVE) + .or() .like("companyChineseName", "*" + keyWords + "*", Case.INSENSITIVE) - /*.or().contains("company", "*" + keyWords + "*") - .or().contains("number", "*" + keyWords + "*")*/ + .or() + .like("company", "*" + keyWords + "*", Case.INSENSITIVE) + .or() + .like("number", "*" + keyWords + "*", Case.INSENSITIVE) .findAll())) .toList() .toObservable(); diff --git a/mobile/src/main/java/io/github/marktony/espresso/mvp/companydetails/CompanyDetailContract.java b/mobile/src/main/java/io/github/marktony/espresso/mvp/companydetails/CompanyDetailContract.java index 74961bc..65d80ef 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/mvp/companydetails/CompanyDetailContract.java +++ b/mobile/src/main/java/io/github/marktony/espresso/mvp/companydetails/CompanyDetailContract.java @@ -21,8 +21,6 @@ interface View extends BaseView { void showErrorMsg(); - - } interface Presenter extends BasePresenter { diff --git a/mobile/src/main/java/io/github/marktony/espresso/mvp/companydetails/CompanyDetailFragment.java b/mobile/src/main/java/io/github/marktony/espresso/mvp/companydetails/CompanyDetailFragment.java index 2f1c7fa..6856d4d 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/mvp/companydetails/CompanyDetailFragment.java +++ b/mobile/src/main/java/io/github/marktony/espresso/mvp/companydetails/CompanyDetailFragment.java @@ -1,19 +1,29 @@ package io.github.marktony.espresso.mvp.companydetails; +import android.content.ActivityNotFoundException; import android.content.Intent; +import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v7.widget.AppCompatTextView; import android.support.v7.widget.Toolbar; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.StyleSpan; +import android.text.style.URLSpan; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import io.github.marktony.espresso.R; +import io.github.marktony.espresso.customtabs.CustomTabsHelper; /** * Created by lizhaotailang on 2017/2/10. @@ -27,10 +37,12 @@ public class CompanyDetailFragment extends Fragment private AppCompatTextView textViewCompanyName; private AppCompatTextView textViewTel; private AppCompatTextView textViewWebsite; - private View layoutTel, layoutWebsite; private CompanyDetailContract.Presenter presenter; + private String tel; + private String website; + public CompanyDetailFragment() {} public static CompanyDetailFragment newInstance() { @@ -52,15 +64,14 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - + share(); } }); - layoutTel.setOnClickListener(new View.OnClickListener() { + textViewTel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - String tel = textViewTel.getText().toString(); - if (!tel.isEmpty()) { + if (tel != null && !tel.isEmpty()) { Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:" + tel)); getActivity().startActivity(intent); @@ -68,13 +79,17 @@ public void onClick(View v) { } }); - layoutWebsite.setOnClickListener(new View.OnClickListener() { + textViewWebsite.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - + if (website != null) { + CustomTabsHelper.openUrl(getContext(), website); + } } }); + setHasOptionsMenu(true); + return view; } @@ -90,6 +105,14 @@ public void onPause() { presenter.unsubscribe(); } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + getActivity().onBackPressed(); + } + return true; + } + @Override public void initViews(View view) { @@ -101,8 +124,6 @@ public void initViews(View view) { textViewCompanyName = (AppCompatTextView) view.findViewById(R.id.textViewCompany); textViewTel = (AppCompatTextView) view.findViewById(R.id.textViewCompanyPhoneNumber); textViewWebsite = (AppCompatTextView) view.findViewById(R.id.textViewCompanyWebsite); - layoutTel = view.findViewById(R.id.layoutCompanyPhoneNumber); - layoutWebsite = view.findViewById(R.id.layoutCompanyOfficialWebsite); } @Override @@ -112,22 +133,51 @@ public void setPresenter(@NonNull CompanyDetailContract.Presenter presenter) { @Override public void setCompanyName(String name) { - textViewCompanyName.setText(name); + String companyName = getString(R.string.company_name) + "\n" + name; + Spannable spannable = new SpannableStringBuilder(companyName); + spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, companyName.length() - name.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.setSpan(new StyleSpan(Typeface.NORMAL), companyName.length() - name.length(), companyName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + textViewCompanyName.setText(spannable); } @Override public void setCompanyTel(String tel) { - textViewTel.setText(tel); + this.tel = tel; + String companyTel = getString(R.string.phone_number) + "\n" + tel; + Spannable spannable = new SpannableStringBuilder(companyTel); + spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, companyTel.length() - tel.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.setSpan(new URLSpan(tel), companyTel.length() - tel.length(), companyTel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + textViewTel.setText(spannable); } @Override public void setCompanyWebsite(String website) { - textViewWebsite.setText(website); + this.website = website; + String ws = getString(R.string.official_website) + "\n" + website; + Spannable spannable = new SpannableStringBuilder(ws); + spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, ws.length() - website.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.setSpan(new URLSpan(website), ws.length() - website.length(), ws.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + textViewWebsite.setText(spannable); } @Override public void showErrorMsg() { + Snackbar.make(fab, R.string.something_wrong, Snackbar.LENGTH_SHORT).show(); + } + public void share() { + String content = textViewCompanyName.getText().toString() + + "\n" + + textViewTel.getText().toString() + + "\n" + + textViewWebsite.getText().toString(); + try { + Intent intent = new Intent().setAction(Intent.ACTION_SEND).setType("text/plain"); + intent.putExtra(Intent.EXTRA_TEXT, content); + startActivity(Intent.createChooser(intent, getString(R.string.share))); + } catch (ActivityNotFoundException e) { + Snackbar.make(fab, R.string.something_wrong, Snackbar.LENGTH_SHORT).show(); + } } } diff --git a/mobile/src/main/java/io/github/marktony/espresso/mvp/packagedetails/PackageDetailsAdapter.java b/mobile/src/main/java/io/github/marktony/espresso/mvp/packagedetails/PackageDetailsAdapter.java index 8324b10..5808bbe 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/mvp/packagedetails/PackageDetailsAdapter.java +++ b/mobile/src/main/java/io/github/marktony/espresso/mvp/packagedetails/PackageDetailsAdapter.java @@ -1,5 +1,6 @@ package io.github.marktony.espresso.mvp.packagedetails; +import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -18,6 +19,7 @@ import io.github.marktony.espresso.component.Timeline; import io.github.marktony.espresso.data.Package; import io.github.marktony.espresso.data.PackageStatus; +import io.github.marktony.espresso.mvp.companydetails.CompanyDetailActivity; import io.realm.RealmList; /** @@ -43,7 +45,7 @@ public class PackageDetailsAdapter extends RecyclerView.Adapter list) { public void OnItemClick(View v, int position) { Intent intent = new Intent(getContext(), PackageDetailsActivity.class); intent.putExtra(PackageDetailsActivity.PACKAGE_ID, list.get(position).getNumber()); - startActivityForResult(intent, REQUEST_OPEN_DETAILS, ActivityOptions.makeSceneTransitionAnimation(getActivity()).toBundle()); + startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(getActivity()).toBundle()); } }); diff --git a/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchFragment.java b/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchFragment.java index acf1d32..2419a7a 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchFragment.java +++ b/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchFragment.java @@ -1,5 +1,7 @@ package io.github.marktony.espresso.mvp.search; +import android.app.ActivityOptions; +import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -19,6 +21,8 @@ import io.github.marktony.espresso.data.Company; import io.github.marktony.espresso.data.Package; import io.github.marktony.espresso.interfaze.OnRecyclerViewItemClickListener; +import io.github.marktony.espresso.mvp.companydetails.CompanyDetailActivity; +import io.github.marktony.espresso.mvp.packagedetails.PackageDetailsActivity; /** * Created by lizhaotailang on 2017/3/18. @@ -109,13 +113,29 @@ public void setPresenter(@NonNull SearchContract.Presenter presenter) { } @Override - public void showResult(List packages, List companies) { + public void showResult(final List packages, final List companies) { + if (packages == null || companies == null) { + return; + } if (adapter == null) { adapter = new SearchResultsAdapter(getContext(), packages, companies); adapter.setOnItemClickListener(new OnRecyclerViewItemClickListener() { @Override public void OnItemClick(View v, int position) { + if (adapter.getItemViewType(position) == SearchResultsAdapter.ItemWrapper.TYPE_PACKAGE) { + + Intent intent = new Intent(getContext(), PackageDetailsActivity.class); + intent.putExtra(PackageDetailsActivity.PACKAGE_ID, packages.get(adapter.getOriginalIndex(position)).getNumber()); + startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(getActivity()).toBundle()); + + } else if (adapter.getItemViewType(position) == SearchResultsAdapter.ItemWrapper.TYPE_COMPANY) { + + Intent intent = new Intent(getContext(), CompanyDetailActivity.class); + intent.putExtra(CompanyDetailActivity.COMPANY_ID, companies.get(adapter.getOriginalIndex(position)).getId()); + startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(getActivity()).toBundle()); + + } } }); recyclerView.setAdapter(adapter); diff --git a/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchPresenter.java b/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchPresenter.java index 14ad52f..11c4e8e 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchPresenter.java +++ b/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchPresenter.java @@ -34,6 +34,8 @@ public class SearchPresenter implements SearchContract.Presenter{ private CompositeDisposable compositeDisposable; + private String queryWords = null; + public SearchPresenter(@NonNull SearchContract.View view, @NonNull PackagesRepository packagesRepository, @NonNull CompaniesRepository companiesRepository) { @@ -46,7 +48,7 @@ public SearchPresenter(@NonNull SearchContract.View view, @Override public void subscribe() { - + search(queryWords); } @Override @@ -57,6 +59,12 @@ public void unsubscribe() { @Override public void search(String keyWords) { + if (keyWords == null || keyWords.isEmpty()) { + view.showResult(null, null); + return; + } + queryWords = keyWords; + Observable> companyObservable = companiesRepository .searchCompanies(keyWords) .subscribeOn(Schedulers.io()); diff --git a/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchResultsAdapter.java b/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchResultsAdapter.java index 4cde14c..91249b4 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchResultsAdapter.java +++ b/mobile/src/main/java/io/github/marktony/espresso/mvp/search/SearchResultsAdapter.java @@ -4,10 +4,8 @@ import android.graphics.Color; import android.graphics.Typeface; import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; import android.support.v7.widget.AppCompatTextView; import android.support.v7.widget.RecyclerView; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -167,14 +165,13 @@ public void updateData(List packages, List companies) { this.packages.clear(); this.companies.clear(); this.list.clear(); - this.packages = packages; - this.companies = companies; this.list.add(new ItemWrapper(ItemWrapper.TYPE_CATEGORY)); if (packages.size() > 0) { for (int i = 0; i < packages.size(); i++) { ItemWrapper wrapper = new ItemWrapper(ItemWrapper.TYPE_PACKAGE); wrapper.index = i; list.add(wrapper); + this.packages.add(packages.get(i)); } } else { list.add(new ItemWrapper(ItemWrapper.TYPE_EMPTY)); @@ -186,6 +183,7 @@ public void updateData(List packages, List companies) { ItemWrapper wrapper = new ItemWrapper(ItemWrapper.TYPE_COMPANY); wrapper.index = i; list.add(wrapper); + this.companies.add(companies.get(i)); } } else { list.add(new ItemWrapper(ItemWrapper.TYPE_EMPTY)); @@ -197,6 +195,10 @@ public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) { this.listener = listener; } + public int getOriginalIndex(int position) { + return list.get(position).index; + } + private class PackageHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ @@ -220,7 +222,7 @@ private class PackageHolder extends RecyclerView.ViewHolder @Override public void onClick(View v) { if (this.listener != null) { - listener.OnItemClick(v, list.get(getLayoutPosition()).index); + listener.OnItemClick(v, getLayoutPosition()); } } } @@ -268,7 +270,7 @@ private class CompanyHolder extends RecyclerView.ViewHolder @Override public void onClick(View v) { if (listener != null) { - listener.OnItemClick(v, list.get(getLayoutPosition()).index); + listener.OnItemClick(v, getLayoutPosition()); } } } diff --git a/mobile/src/main/java/io/github/marktony/espresso/retrofit/Api.java b/mobile/src/main/java/io/github/marktony/espresso/retrofit/Api.java index c667cbf..e8cdba9 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/retrofit/Api.java +++ b/mobile/src/main/java/io/github/marktony/espresso/retrofit/Api.java @@ -7,7 +7,6 @@ public class Api { - // Base API public static final String API_BASE = "http://www.kuaidi100.com/"; diff --git a/mobile/src/main/java/io/github/marktony/espresso/service/ReminderService.java b/mobile/src/main/java/io/github/marktony/espresso/service/ReminderService.java index 3a8d3b3..7810290 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/service/ReminderService.java +++ b/mobile/src/main/java/io/github/marktony/espresso/service/ReminderService.java @@ -25,15 +25,14 @@ import io.github.marktony.espresso.realm.RealmHelper; import io.github.marktony.espresso.retrofit.RetrofitClient; import io.github.marktony.espresso.retrofit.RetrofitService; -import io.github.marktony.espresso.util.PushUtils; -import io.github.marktony.espresso.util.SettingsUtils; +import io.github.marktony.espresso.util.NetworkUtil; +import io.github.marktony.espresso.util.PushUtil; +import io.github.marktony.espresso.util.SettingsUtil; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; import io.realm.Realm; -import static io.github.marktony.espresso.realm.RealmHelper.DATABASE_NAME; - /** * Created by lizhaotailang on 2017/3/8. * Background service to build notifications and send them to user. @@ -74,12 +73,12 @@ protected void onHandleIntent(@Nullable Intent intent) { Log.d(TAG, "onHandleIntent: "); - boolean isDisturbMode = preference.getBoolean(SettingsUtils.KEY_DO_NOT_DISTURB_MODE, true); + boolean isDisturbMode = preference.getBoolean(SettingsUtil.KEY_DO_NOT_DISTURB_MODE, true); // The alert mode is off // or DO-NOT-DISTURB-MODE is off // or time now is not in the DO-NOT-DISTURB-MODE range. - if (isDisturbMode && PushUtils.isInDisturbTime(this, Calendar.getInstance())) { + if (isDisturbMode && PushUtil.isInDisturbTime(this, Calendar.getInstance())) { return; } @@ -96,7 +95,6 @@ protected void onHandleIntent(@Nullable Intent intent) { // Avoid repeated pushing if (p.isPushable()) { - Realm realm = RealmHelper.newRealmInstance(); p.setPushable(false); @@ -108,7 +106,7 @@ protected void onHandleIntent(@Nullable Intent intent) { realm.commitTransaction(); realm.close(); - } else { + } else if (NetworkUtil.networkConnected(getApplicationContext())) { refreshPackage(i, results.get(i)); } diff --git a/mobile/src/main/java/io/github/marktony/espresso/ui/AboutFragment.java b/mobile/src/main/java/io/github/marktony/espresso/ui/AboutFragment.java index 0b7c256..8882c8b 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/ui/AboutFragment.java +++ b/mobile/src/main/java/io/github/marktony/espresso/ui/AboutFragment.java @@ -14,6 +14,7 @@ import io.github.marktony.espresso.BuildConfig; import io.github.marktony.espresso.R; +import io.github.marktony.espresso.customtabs.CustomTabsHelper; import static android.content.Context.CLIPBOARD_SERVICE; @@ -68,7 +69,7 @@ public boolean onPreferenceClick(Preference preference) { prefThx1.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - + CustomTabsHelper.openUrl(getContext(), getString(R.string.thanks_1_desc)); return true; } }); @@ -77,7 +78,7 @@ public boolean onPreferenceClick(Preference preference) { prefThx2.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - + CustomTabsHelper.openUrl(getContext(), getString(R.string.thanks_2_url)); return true; } }); @@ -86,7 +87,7 @@ public boolean onPreferenceClick(Preference preference) { prefSourceCode.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - + CustomTabsHelper.openUrl(getContext(), getString(R.string.source_code_desc)); return true; } }); diff --git a/mobile/src/main/java/io/github/marktony/espresso/ui/SettingsFragment.java b/mobile/src/main/java/io/github/marktony/espresso/ui/SettingsFragment.java index b9789ca..091d9b4 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/ui/SettingsFragment.java +++ b/mobile/src/main/java/io/github/marktony/espresso/ui/SettingsFragment.java @@ -10,9 +10,9 @@ import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; import io.github.marktony.espresso.R; -import io.github.marktony.espresso.util.PushUtils; -import io.github.marktony.espresso.util.SettingsUtils; -import io.github.marktony.espresso.util.TimeFormatUtils; +import io.github.marktony.espresso.util.PushUtil; +import io.github.marktony.espresso.util.SettingsUtil; +import io.github.marktony.espresso.util.TimeFormatUtil; /** * Created by lizhaotailang on 2017/3/15. @@ -37,13 +37,13 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { sp = PreferenceManager.getDefaultSharedPreferences(getContext()); // Set the do-not-disturb-mode time initial range: // from 23:00 to 6:00 - startHour = sp.getInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_START_HOUR, 23); - startMinute = sp.getInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_START_MINUTE, 0); - prefStartTime.setSummary(TimeFormatUtils.formatTimeIntToString(startHour, startMinute)); + startHour = sp.getInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_START_HOUR, 23); + startMinute = sp.getInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_START_MINUTE, 0); + prefStartTime.setSummary(TimeFormatUtil.formatTimeIntToString(startHour, startMinute)); - endHour = sp.getInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_END_HOUR, 6); - endMinute = sp.getInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_END_MINUTE, 0); - prefsEndTime.setSummary(TimeFormatUtils.formatTimeIntToString(endHour, endMinute)); + endHour = sp.getInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_END_HOUR, 6); + endMinute = sp.getInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_END_MINUTE, 0); + prefsEndTime.setSummary(TimeFormatUtil.formatTimeIntToString(endHour, endMinute)); prefStartTime.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override @@ -54,11 +54,11 @@ public boolean onPreferenceClick(Preference preference) { public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int second) { // Save the hour and minute value to shared preferences SharedPreferences.Editor editor = sp.edit(); - editor.putInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_START_HOUR, hourOfDay); - editor.putInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_START_MINUTE, minute); + editor.putInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_START_HOUR, hourOfDay); + editor.putInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_START_MINUTE, minute); editor.apply(); // Update ui - prefStartTime.setSummary(TimeFormatUtils.formatTimeIntToString(hourOfDay, minute)); + prefStartTime.setSummary(TimeFormatUtil.formatTimeIntToString(hourOfDay, minute)); } // The final params setting true means that it is 24 hours mode. }, startHour, startMinute, true); @@ -81,10 +81,10 @@ public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int seco } // Save the hour and minute value to shared preferences SharedPreferences.Editor editor = sp.edit(); - editor.putInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_END_HOUR, hourOfDay); - editor.putInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_END_MINUTE, minute); + editor.putInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_END_HOUR, hourOfDay); + editor.putInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_END_MINUTE, minute); editor.apply(); - prefsEndTime.setSummary(TimeFormatUtils.formatTimeIntToString(hourOfDay, minute)); + prefsEndTime.setSummary(TimeFormatUtil.formatTimeIntToString(hourOfDay, minute)); } // The final params setting true means that it is 24 hours mode. }, endHour, endMinute, true); @@ -99,9 +99,9 @@ public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int seco public boolean onPreferenceChange(Preference preference, Object newValue) { boolean value = (boolean) newValue; if (value) { - PushUtils.startReminderService(getContext()); + PushUtil.startReminderService(getContext()); } else { - PushUtils.stopReminderService(getContext()); + PushUtil.stopReminderService(getContext()); } return true; } @@ -111,9 +111,9 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { SharedPreferences.Editor editor = sp.edit(); - editor.putString(SettingsUtils.KEY_NOTIFICATION_INTERVAL, (String)newValue); + editor.putString(SettingsUtil.KEY_NOTIFICATION_INTERVAL, (String)newValue); editor.apply(); - PushUtils.restartReminderService(getContext()); + PushUtil.restartReminderService(getContext()); return true; } }); diff --git a/mobile/src/main/java/io/github/marktony/espresso/ui/onboarding/OnboardingActivity.java b/mobile/src/main/java/io/github/marktony/espresso/ui/onboarding/OnboardingActivity.java index 975ce42..a1dd378 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/ui/onboarding/OnboardingActivity.java +++ b/mobile/src/main/java/io/github/marktony/espresso/ui/onboarding/OnboardingActivity.java @@ -21,7 +21,7 @@ import io.github.marktony.espresso.data.source.CompaniesRepository; import io.github.marktony.espresso.data.source.local.CompaniesLocalDataSource; import io.github.marktony.espresso.mvp.packages.MainActivity; -import io.github.marktony.espresso.util.SettingsUtils; +import io.github.marktony.espresso.util.SettingsUtil; public class OnboardingActivity extends AppCompatActivity { @@ -42,7 +42,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); - if (sp.getBoolean(SettingsUtils.KEY_FIRST_LAUNCH, true)) { + if (sp.getBoolean(SettingsUtil.KEY_FIRST_LAUNCH, true)) { setContentView(R.layout.activity_onboarding); @@ -80,7 +80,7 @@ public void onPageScrollStateChanged(int state) { @Override public void onClick(View v) { SharedPreferences.Editor ed = sp.edit(); - ed.putBoolean(SettingsUtils.KEY_FIRST_LAUNCH, false); + ed.putBoolean(SettingsUtil.KEY_FIRST_LAUNCH, false); ed.apply(); navigateToMainActivity(); } diff --git a/mobile/src/main/java/io/github/marktony/espresso/util/NetworkUtil.java b/mobile/src/main/java/io/github/marktony/espresso/util/NetworkUtil.java new file mode 100644 index 0000000..5ad7683 --- /dev/null +++ b/mobile/src/main/java/io/github/marktony/espresso/util/NetworkUtil.java @@ -0,0 +1,26 @@ +package io.github.marktony.espresso.util; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +/** + * Created by lizhaotailang on 2017/3/27. + */ + +public class NetworkUtil { + + // whether connect to internet + public static boolean networkConnected(Context context){ + + if (context != null){ + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo info = manager.getActiveNetworkInfo(); + if (info != null) + return info.isAvailable(); + } + + return false; + } + +} diff --git a/mobile/src/main/java/io/github/marktony/espresso/util/PushUtils.java b/mobile/src/main/java/io/github/marktony/espresso/util/PushUtil.java similarity index 84% rename from mobile/src/main/java/io/github/marktony/espresso/util/PushUtils.java rename to mobile/src/main/java/io/github/marktony/espresso/util/PushUtil.java index 8cc9f9b..834c432 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/util/PushUtils.java +++ b/mobile/src/main/java/io/github/marktony/espresso/util/PushUtil.java @@ -16,14 +16,14 @@ * Created by lizhaotailang on 2017/3/18. */ -public class PushUtils { +public class PushUtil { - public static final String TAG = PushUtils.class.getSimpleName(); + public static final String TAG = PushUtil.class.getSimpleName(); public static void startAlarmService(Context context, Class service, long interval) { boolean alert = PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(SettingsUtils.KEY_ALERT, true); + .getBoolean(SettingsUtil.KEY_ALERT, true); if (alert) { AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); @@ -45,7 +45,7 @@ public static void stopAlarmService(Context context, Class service) { public static void startReminderService(Context context) { // Default value is 30 minutes int intervalTime = getIntervalTime(Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context) - .getString(SettingsUtils.KEY_NOTIFICATION_INTERVAL, "1"))); + .getString(SettingsUtil.KEY_NOTIFICATION_INTERVAL, "1"))); if (intervalTime > -1) { startAlarmService(context, ReminderService.class, intervalTime); Log.d(TAG, "startReminderService: interval time " + intervalTime); @@ -63,10 +63,10 @@ public static void restartReminderService(Context context) { public static boolean isInDisturbTime(Context context, Calendar calendar) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); - int startHour = sp.getInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_START_HOUR, 23); - int startMinute = sp.getInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_START_MINUTE, 0); - int endHour = sp.getInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_END_HOUR, 6); - int endMinute = sp.getInt(SettingsUtils.KEY_DO_NOT_DISTURB_MODE_END_MINUTE, 0); + int startHour = sp.getInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_START_HOUR, 23); + int startMinute = sp.getInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_START_MINUTE, 0); + int endHour = sp.getInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_END_HOUR, 6); + int endMinute = sp.getInt(SettingsUtil.KEY_DO_NOT_DISTURB_MODE_END_MINUTE, 0); int nowHour = calendar.get(Calendar.HOUR_OF_DAY); int nowMinute = calendar.get(Calendar.MINUTE); return (nowHour >= startHour && nowMinute >= startMinute) && (nowHour <= endHour && nowMinute <= endMinute); diff --git a/mobile/src/main/java/io/github/marktony/espresso/util/SettingsUtils.java b/mobile/src/main/java/io/github/marktony/espresso/util/SettingsUtil.java similarity index 82% rename from mobile/src/main/java/io/github/marktony/espresso/util/SettingsUtils.java rename to mobile/src/main/java/io/github/marktony/espresso/util/SettingsUtil.java index 4463666..885935b 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/util/SettingsUtils.java +++ b/mobile/src/main/java/io/github/marktony/espresso/util/SettingsUtil.java @@ -4,8 +4,7 @@ * Created by lizhaotailang on 2017/3/23. */ -public class SettingsUtils { - +public class SettingsUtil { public static final String KEY_ALERT = "alert"; public static final String KEY_DO_NOT_DISTURB_MODE = "do_not_disturb_mode"; @@ -16,4 +15,9 @@ public class SettingsUtils { public static final String KEY_NOTIFICATION_INTERVAL = "notification_interval"; public static final String KEY_FIRST_LAUNCH = "first_launch"; + + public static final String KEY_CUSTOM_TABS = "chrome_custom_tabs"; + + public static final String KEY_NIGHT_MODE = "night_mode"; + } diff --git a/mobile/src/main/java/io/github/marktony/espresso/util/TimeFormatUtils.java b/mobile/src/main/java/io/github/marktony/espresso/util/TimeFormatUtil.java similarity index 96% rename from mobile/src/main/java/io/github/marktony/espresso/util/TimeFormatUtils.java rename to mobile/src/main/java/io/github/marktony/espresso/util/TimeFormatUtil.java index 98fe954..0d28e7b 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/util/TimeFormatUtils.java +++ b/mobile/src/main/java/io/github/marktony/espresso/util/TimeFormatUtil.java @@ -6,7 +6,7 @@ * Created by lizhaotailang on 2017/3/17. */ -public class TimeFormatUtils { +public class TimeFormatUtil { public static String formatTimeIntToString(int hour, int minute) { StringBuilder buffer = new StringBuilder(16); diff --git a/mobile/src/main/res/anim/fade_in.xml b/mobile/src/main/res/anim/fade_in.xml new file mode 100644 index 0000000..5189076 --- /dev/null +++ b/mobile/src/main/res/anim/fade_in.xml @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/anim/fade_out.xml b/mobile/src/main/res/anim/fade_out.xml new file mode 100644 index 0000000..81eb085 --- /dev/null +++ b/mobile/src/main/res/anim/fade_out.xml @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/ic_link_black_24dp.xml b/mobile/src/main/res/drawable/ic_link_black_24dp.xml new file mode 100644 index 0000000..538c5bd --- /dev/null +++ b/mobile/src/main/res/drawable/ic_link_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/mobile/src/main/res/drawable/ic_location_city_black_24dp.xml b/mobile/src/main/res/drawable/ic_location_city_black_24dp.xml new file mode 100644 index 0000000..a7c688f --- /dev/null +++ b/mobile/src/main/res/drawable/ic_location_city_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/mobile/src/main/res/layout/fragment_company_details.xml b/mobile/src/main/res/layout/fragment_company_details.xml index 26c2b89..0ef37f6 100644 --- a/mobile/src/main/res/layout/fragment_company_details.xml +++ b/mobile/src/main/res/layout/fragment_company_details.xml @@ -54,69 +54,37 @@ - - - - - - - - - + android:layout_marginTop="@dimen/activity_margin_half" + android:layout_marginBottom="@dimen/activity_margin_half" + android:drawableStart="@drawable/ic_phone_black_24dp" + android:lineSpacingExtra="@dimen/activity_margin_half" + android:drawablePadding="@dimen/activity_horizontal_margin" + android:id="@+id/textViewCompanyPhoneNumber" + android:textIsSelectable="true"/> - - - - - - - + android:layout_marginTop="@dimen/activity_margin_half" + android:layout_marginBottom="@dimen/activity_margin_half" + android:drawableStart="@drawable/ic_link_black_24dp" + android:drawablePadding="@dimen/activity_horizontal_margin" + android:id="@+id/textViewCompanyWebsite" + android:textAppearance="@style/TextAppearance.AppCompat.Small" + android:lineSpacingExtra="@dimen/activity_margin_half" + android:textIsSelectable="true"/> diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index 54b41bc..14a1c3f 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -94,6 +94,9 @@ End time 06:00 Notification interval + Browser + Chrome custom tabs + Open links with Chrome Custom Tabs User interface Navigation bar tint Color the navigation bar @@ -121,8 +124,10 @@ Thanks FengGo Package Tracker Project + https://github.com/fython/PackageTracker +Youlun Zhai Poster designer + https://plus.google.com/+YoulunZhai Source code https://github.com/TonnyL/Espresso Support @@ -169,5 +174,8 @@ Loading… + + No browser installed on the device. + \ No newline at end of file diff --git a/mobile/src/main/res/values/styles.xml b/mobile/src/main/res/values/styles.xml index cb66cdb..e63f498 100644 --- a/mobile/src/main/res/values/styles.xml +++ b/mobile/src/main/res/values/styles.xml @@ -35,4 +35,9 @@ 1 + + diff --git a/mobile/src/main/res/xml/settings_prefs.xml b/mobile/src/main/res/xml/settings_prefs.xml index 29bf0fa..9f4f029 100644 --- a/mobile/src/main/res/xml/settings_prefs.xml +++ b/mobile/src/main/res/xml/settings_prefs.xml @@ -41,6 +41,18 @@ + + + + + + +