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…