From 78157343be9a97ee519d26c43b4650b0cf6c28a0 Mon Sep 17 00:00:00 2001 From: lizhaotailang Date: Mon, 27 Mar 2017 18:45:31 +0800 Subject: [PATCH] Initial commit --- .idea/inspectionProfiles/Project_Default.xml | 5 ++ README.md | 33 ++++++++---- .../local/CompaniesLocalDataSource.java | 21 ++------ .../source/local/PackagesLocalDataSource.java | 50 ++++--------------- .../marktony/espresso/realm/RealmHelper.java | 10 ++++ .../espresso/service/ReminderService.java | 17 ++----- .../ui/onboarding/OnboardingActivity.java | 7 +-- .../ui/onboarding/OnboardingFragment.java | 14 +++--- ...ck_24dp.xml => ic_beenhere_black_24dp.xml} | 5 +- .../drawable/ic_notifications_black_24dp.xml | 9 ++++ .../main/res/layout/activity_onboarding.xml | 1 + .../main/res/layout/fragment_onboarding.xml | 3 +- mobile/src/main/res/values/strings.xml | 7 +++ 13 files changed, 85 insertions(+), 97 deletions(-) rename mobile/src/main/res/drawable/{ic_flight_black_24dp.xml => ic_beenhere_black_24dp.xml} (51%) create mode 100644 mobile/src/main/res/drawable/ic_notifications_black_24dp.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index da87712..bfb03b7 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,6 +1,11 @@ \ No newline at end of file diff --git a/README.md b/README.md index 5a707ff..0bf9d04 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,26 @@ # 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. -The source code in this repository reflects the app which supports mobile devices running Android 5.0+ and wearable devices running Android Wear 2.0+. +The source code in this repository reflects the app which supports mobile devices running Android 5.0+. ### Features With this app, you can: ++ Support over 600 express companies. + Add packages by inputting the package number or just scanning the express sheet. -+ View the package's detais such as the latest location -+ Search infomation about the express companies. ++ Recognize the company of a package automatically. ++ View the package's details such as the latest location. ++ Search information about the express companies. ++ Launcher widgets. + Get important notification when the package is on delivery. + Send feedback on using experience from your devices. -+ Support Android Wear devices. + +### Screenshots +![screenshot0](http://upload-images.jianshu.io/upload_images/2440049-649b96f3b8858cce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + +![screenshot1](http://upload-images.jianshu.io/upload_images/2440049-d3c50d9e5ca6f0a4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### 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. @@ -32,7 +41,7 @@ Notice: If you want to review a different branch, replace the `master` with the Suggestion: It is better for you to update your Android Studio to version 2.3 when you open this project. -### Todos +### To-dos This project is still in progress. Here are the some features that I will finish in the future. - [x] Refreshing package details by accessing the network. @@ -40,7 +49,7 @@ This project is still in progress. Here are the some features that I will finish - [x] App Shortcuts on devices that running Android 7.1+. - [x] Material design app onboarding pages. - [ ] Chrome Custom Tabs. -- [ ] Alphabet indexing for companies list. +- [x] Alphabet indexing for companies list. - [ ] Search packages and companies. - [ ] Day and night mode. - [x] Service to build notifications. @@ -48,6 +57,10 @@ This project is still in progress. Here are the some features that I will finish - [ ] Supporting Android Wear. - [ ] UI test and unit test. +### Help Me Improve This App ++ As you can see at the screenshots, some images in Espresso app are not suitable. So if you are a designer and familiar with **Material Design** and want to help me make the app look better, please email me. ++ If you want to improve the translation of Espresso, do not hesitate to email me. Let us make Espresso more and more popular all over the world. + ### Libraries Used in This App Name | Introduction | Version ----- | ------ | --- @@ -63,9 +76,11 @@ Name | Introduction | Version ### Thanks to + [Express 100](https://www.kuaidi100.com/) -+ [googlesamples](https://github.com/googlesamples) - [android-architecture](https://github.com/googlesamples/android-architecture) -+ [google](https://github.com/google) - [iosched](https://github.com/google/iosched) -+ [fython](https://github.com/fython) - [PackageTracker](https://github.com/fython/PackageTracker) ++ [googlesamples](https://github.com/googlesamples) - [android-architecture](https://github.com/googlesamples/android-architecture):A collection of samples to discuss and showcase different architectural tools and patterns for Android apps. ++ [google](https://github.com/google) - [iosched](https://github.com/google/iosched):The Google I/O 2016 Android App. ++ [fython](https://github.com/fython) - [PackageTracker](https://github.com/fython/PackageTracker):The New ExpressHelper for Android. ++ [hefuyicoder](https://github.com/hefuyicoder) - [ListenerMusicPlayer](https://github.com/hefuyicoder/ListenerMusicPlayer):A Grace Material Design Music Player. ++ [BreadKid](https://github.com/BreadKid) - [SearchItem](https://github.com/BreadKid/SearchItem):小搜搜——商品条形码/二维码搜索APP. + [YoulunZhai](https://plus.google.com/+YoulunZhai) - The posters. + Other people who help me solve the problems when I met some difficult bugs. diff --git a/mobile/src/main/java/io/github/marktony/espresso/data/source/local/CompaniesLocalDataSource.java b/mobile/src/main/java/io/github/marktony/espresso/data/source/local/CompaniesLocalDataSource.java index d1ae16a..1543c64 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/data/source/local/CompaniesLocalDataSource.java +++ b/mobile/src/main/java/io/github/marktony/espresso/data/source/local/CompaniesLocalDataSource.java @@ -11,7 +11,6 @@ import io.reactivex.Observable; import io.realm.Case; import io.realm.Realm; -import io.realm.RealmConfiguration; import io.realm.Sort; /** @@ -37,10 +36,7 @@ public static CompaniesLocalDataSource getInstance() { @Override public Observable> getCompanies() { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); return Observable .fromIterable(rlm.copyFromRealm(rlm.where(Company.class).findAllSorted("alphabet", Sort.ASCENDING))) .toList() @@ -49,20 +45,14 @@ public Observable> getCompanies() { @Override public Observable getCompany(@NonNull String companyId) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); return Observable .just(rlm.copyFromRealm(rlm.where(Company.class).equalTo("id", companyId).findFirst())); } @Override public void initData() { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); rlm.beginTransaction(); rlm.createOrUpdateObjectFromJson(Company.class, "{'name':'申通快递','id':'shentong','tel':'95543','website':'http://www.sto.cn','alphabet':'shentongkuaidi','avatar':'#00BCD4'}"); @@ -713,10 +703,7 @@ public void initData() { @Override public Observable> searchCompanies(@NonNull String keyWords) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); List results = rlm.copyFromRealm( rlm.where(Company.class) .like("name","*" + keyWords + "*", Case.INSENSITIVE) 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 4bf6d46..70dd80a 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 @@ -11,7 +11,6 @@ import io.reactivex.Observable; import io.realm.Case; import io.realm.Realm; -import io.realm.RealmConfiguration; import io.realm.RealmResults; import io.realm.Sort; @@ -49,10 +48,7 @@ public static void destroyInstance() { */ @Override public Observable> getPackages() { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); return Observable.just(rlm.copyFromRealm(rlm.where(Package.class) .findAllSorted("timestamp", Sort.DESCENDING))); @@ -67,10 +63,7 @@ public Observable> getPackages() { */ @Override public Observable getPackage(@NonNull String packNumber) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); return Observable.just(rlm.copyFromRealm(rlm.where(Package.class) .equalTo("number", packNumber) .findFirst())); @@ -82,10 +75,7 @@ public Observable getPackage(@NonNull String packNumber) { */ @Override public void savePackage(@NonNull Package pack) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); // DO NOT forget begin and commit the transaction. rlm.beginTransaction(); rlm.copyToRealmOrUpdate(pack); @@ -101,10 +91,7 @@ public void savePackage(@NonNull Package pack) { */ @Override public void deletePackage(@NonNull String packageId) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); Package p = rlm.where(Package.class) .equalTo("number", packageId) .findFirst(); @@ -135,10 +122,7 @@ public Observable refreshPackage(@NonNull String packageId) { */ @Override public void setAllPackagesRead() { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); List results = rlm.copyFromRealm(rlm.where(Package.class).findAll()); for (Package p : results) { @@ -160,10 +144,7 @@ public void setAllPackagesRead() { */ @Override public void setPackageReadable(@NonNull String packageId, boolean readable) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); Package p = rlm.copyFromRealm(rlm.where(Package.class) .equalTo("number", packageId) .findFirst()); @@ -186,10 +167,7 @@ public void setPackageReadable(@NonNull String packageId, boolean readable) { */ @Override public boolean isPackageExist(@NonNull String packageId) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); RealmResults results = rlm.where(Package.class) .equalTo("number", packageId) .findAll(); @@ -198,10 +176,7 @@ public boolean isPackageExist(@NonNull String packageId) { @Override public void updatePackageName(@NonNull String packageId, @NonNull String name) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); Package p = rlm.where(Package.class) .equalTo("number", packageId) .findFirst(); @@ -216,7 +191,7 @@ public void updatePackageName(@NonNull String packageId, @NonNull String name) { @Override public Observable> searchPackages(@NonNull String keyWords) { - Realm rlm = newRealmInstance(); + Realm rlm = RealmHelper.newRealmInstance(); return Observable.fromIterable(rlm.copyFromRealm( rlm.where(Package.class) .like("companyChineseName", "*" + keyWords + "*", Case.INSENSITIVE) @@ -227,11 +202,4 @@ public Observable> searchPackages(@NonNull String keyWords) { .toObservable(); } - private Realm newRealmInstance() { - return Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(RealmHelper.DATABASE_NAME) - .build()); - } - } diff --git a/mobile/src/main/java/io/github/marktony/espresso/realm/RealmHelper.java b/mobile/src/main/java/io/github/marktony/espresso/realm/RealmHelper.java index 5330b09..e8f467b 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/realm/RealmHelper.java +++ b/mobile/src/main/java/io/github/marktony/espresso/realm/RealmHelper.java @@ -1,5 +1,8 @@ package io.github.marktony.espresso.realm; +import io.realm.Realm; +import io.realm.RealmConfiguration; + /** * Created by lizhaotailang on 2017/3/22. */ @@ -8,4 +11,11 @@ public class RealmHelper { public static final String DATABASE_NAME = "Espresso.realm"; + public static Realm newRealmInstance() { + return Realm.getInstance(new RealmConfiguration.Builder() + .deleteRealmIfMigrationNeeded() + .name(RealmHelper.DATABASE_NAME) + .build()); + } + } 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 731f1df..3a8d3b3 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 @@ -22,6 +22,7 @@ import io.github.marktony.espresso.appwidget.AppWidgetProvider; import io.github.marktony.espresso.data.Package; import io.github.marktony.espresso.mvp.packagedetails.PackageDetailsActivity; +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; @@ -30,7 +31,6 @@ import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; import io.realm.Realm; -import io.realm.RealmConfiguration; import static io.github.marktony.espresso.realm.RealmHelper.DATABASE_NAME; @@ -83,10 +83,7 @@ protected void onHandleIntent(@Nullable Intent intent) { return; } - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); List results = rlm.copyFromRealm( rlm.where(Package.class) @@ -100,10 +97,7 @@ protected void onHandleIntent(@Nullable Intent intent) { if (p.isPushable()) { - Realm realm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(DATABASE_NAME) - .build()); + Realm realm = RealmHelper.newRealmInstance(); p.setPushable(false); @@ -225,10 +219,7 @@ public void accept(Package aPackage) throws Exception { if (aPackage != null && aPackage.getData().size() > p.getData().size()) { - Realm rlm = Realm.getInstance(new RealmConfiguration.Builder() - .deleteRealmIfMigrationNeeded() - .name(DATABASE_NAME) - .build()); + Realm rlm = RealmHelper.newRealmInstance(); p.setReadable(true); p.setPushable(false); 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 2699944..975ce42 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 @@ -41,11 +41,6 @@ public class OnboardingActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Set the navigation bar color - if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("navigation_bar_tint", true)) { - getWindow().setNavigationBarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark)); - } - final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); if (sp.getBoolean(SettingsUtils.KEY_FIRST_LAUNCH, true)) { @@ -121,6 +116,7 @@ private void initViews() { viewPager = (ViewPager) findViewById(R.id.container); viewPager.setAdapter(pagerAdapter); buttonFinish = (AppCompatButton) findViewById(R.id.buttonFinish); + buttonFinish.setText(R.string.onboarding_finish_button_description_wait); buttonFinish.setEnabled(false); buttonNext = (ImageButton) findViewById(R.id.imageButtonNext); buttonPre = (ImageButton) findViewById(R.id.imageButtonPre); @@ -148,6 +144,7 @@ private void updateIndicators(int position) { public void handleMessage(Message msg) { switch (msg.what) { case MSG_DATA_INSERT_FINISH: + buttonFinish.setText(R.string.onboarding_finish_button_description); buttonFinish.setEnabled(true); break; } diff --git a/mobile/src/main/java/io/github/marktony/espresso/ui/onboarding/OnboardingFragment.java b/mobile/src/main/java/io/github/marktony/espresso/ui/onboarding/OnboardingFragment.java index 05d8692..4d6a441 100644 --- a/mobile/src/main/java/io/github/marktony/espresso/ui/onboarding/OnboardingFragment.java +++ b/mobile/src/main/java/io/github/marktony/espresso/ui/onboarding/OnboardingFragment.java @@ -51,17 +51,19 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa switch (page) { case 0: - sectionImg.setBackgroundResource(R.drawable.ic_flight_black_24dp); - sectionLabel.setText("Section 1"); - // set intro + sectionImg.setBackgroundResource(R.drawable.ic_beenhere_black_24dp); + sectionLabel.setText(R.string.onboarding_section_1); + sectionIntro.setText(R.string.onboarding_intro_1); break; case 1: - sectionImg.setBackgroundResource(R.drawable.ic_local_shipping_black_24dp); - sectionLabel.setText("Section 2"); + sectionImg.setBackgroundResource(R.drawable.ic_notifications_black_24dp); + sectionLabel.setText(R.string.onboarding_section_2); + sectionIntro.setText(R.string.onboarding_intro_2); break; case 2: sectionImg.setBackgroundResource(R.drawable.ic_watch_black_24dp); - sectionLabel.setText("Section 3"); + sectionLabel.setText(R.string.onboarding_section_3); + sectionIntro.setText(R.string.onboarding_intro_3); break; default: break; diff --git a/mobile/src/main/res/drawable/ic_flight_black_24dp.xml b/mobile/src/main/res/drawable/ic_beenhere_black_24dp.xml similarity index 51% rename from mobile/src/main/res/drawable/ic_flight_black_24dp.xml rename to mobile/src/main/res/drawable/ic_beenhere_black_24dp.xml index 55a8d22..5f1c051 100644 --- a/mobile/src/main/res/drawable/ic_flight_black_24dp.xml +++ b/mobile/src/main/res/drawable/ic_beenhere_black_24dp.xml @@ -5,8 +5,5 @@ android:viewportHeight="24.0"> - + android:pathData="M19,1L5,1c-1.1,0 -1.99,0.9 -1.99,2L3,15.93c0,0.69 0.35,1.3 0.88,1.66L12,23l8.11,-5.41c0.53,-0.36 0.88,-0.97 0.88,-1.66L21,3c0,-1.1 -0.9,-2 -2,-2zM10,16l-5,-5 1.41,-1.41L10,13.17l7.59,-7.59L19,7l-9,9z"/> diff --git a/mobile/src/main/res/drawable/ic_notifications_black_24dp.xml b/mobile/src/main/res/drawable/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..7009a67 --- /dev/null +++ b/mobile/src/main/res/drawable/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/mobile/src/main/res/layout/activity_onboarding.xml b/mobile/src/main/res/layout/activity_onboarding.xml index 44fe1b2..31bcf3d 100644 --- a/mobile/src/main/res/layout/activity_onboarding.xml +++ b/mobile/src/main/res/layout/activity_onboarding.xml @@ -83,6 +83,7 @@ android:layout_height="wrap_content" android:layout_gravity="end|center" android:text="@string/onboarding_finish_button_description" + android:contentDescription="@string/onboarding_finish_button_description" android:textColor="@android:color/white" android:visibility="gone" /> diff --git a/mobile/src/main/res/layout/fragment_onboarding.xml b/mobile/src/main/res/layout/fragment_onboarding.xml index ae764f6..73c949c 100644 --- a/mobile/src/main/res/layout/fragment_onboarding.xml +++ b/mobile/src/main/res/layout/fragment_onboarding.xml @@ -15,7 +15,6 @@ android:layout_gravity="center" android:adjustViewBounds="true" android:alpha="0.30" - android:background="@drawable/ic_flight_black_24dp" android:scaleType="fitCenter" /> @@ -32,6 +31,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/section_label" + android:textAlignment="center" style="@style/TextAppearance.AppCompat.Headline" android:textColor="@android:color/white" tools:text="Page One" /> @@ -44,7 +44,6 @@ android:layout_marginTop="@dimen/activity_horizontal_margin" android:alpha="0.7" android:gravity="center" - android:text="Add a long description here about your app's important feature." android:textColor="@android:color/white" /> diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index 43a511d..54b41bc 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -152,6 +152,13 @@ Next Finish Pre + Add your packages quickly and easily + Support 640+ express companies all over the world, but when you add packages, the companies will be recognized automatically. + Keep the delivery status updated + Push notification when the delivery status is refreshed, so you can get the latest information. + Sync with your Android Wear devices + You can make everything done on your watches. + Preparing, please wait…