diff --git a/.idea/modules.xml b/.idea/modules.xml
index bf4147c..816a809 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -3,8 +3,11 @@
+
+
+
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..84db3e7
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,18 @@
+language: android
+
+android:
+ components:
+ - tools
+ - platform-tools
+ - build-tools-25.0.2
+ - android-25
+ - extra-android-m2repository
+ - extra-google-google_play_services
+
+jdk:
+ - oraclejdk8
+
+notifications:
+ email: false
+
+script: ./gradlew assemble check
diff --git a/mobile/src/main/java/io/github/marktony/espresso/data/source/CompaniesRepository.java b/mobile/src/main/java/io/github/marktony/espresso/data/source/CompaniesRepository.java
index ea0808a..97c7ccb 100644
--- a/mobile/src/main/java/io/github/marktony/espresso/data/source/CompaniesRepository.java
+++ b/mobile/src/main/java/io/github/marktony/espresso/data/source/CompaniesRepository.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright(c) 2017 lizhaotailang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package io.github.marktony.espresso.data.source;
import android.support.annotation.NonNull;
@@ -52,4 +68,4 @@ public Observable> searchCompanies(@NonNull String keyWords) {
return localDataSource.searchCompanies(keyWords);
}
-}
\ No newline at end of file
+}
diff --git a/mobile/src/main/java/io/github/marktony/espresso/data/source/PackagesRepository.java b/mobile/src/main/java/io/github/marktony/espresso/data/source/PackagesRepository.java
index f7819d2..e736f86 100644
--- a/mobile/src/main/java/io/github/marktony/espresso/data/source/PackagesRepository.java
+++ b/mobile/src/main/java/io/github/marktony/espresso/data/source/PackagesRepository.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright(c) 2017 lizhaotailang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package io.github.marktony.espresso.data.source;
import android.support.annotation.NonNull;
@@ -40,8 +56,6 @@ public class PackagesRepository implements PackagesDataSource {
private Map cachedPackages;
- private Package cachePackage = null;
-
// Prevent direct instantiation
private PackagesRepository(@NonNull PackagesDataSource packagesRemoteDataSource,
@NonNull PackagesDataSource packagesLocalDataSource) {
@@ -158,7 +172,6 @@ public void savePackage(@NonNull Package pack) {
*/
@Override
public void deletePackage(@NonNull String packageId) {
- cachePackage = getPackageWithNumber(packageId);
packagesLocalDataSource.deletePackage(packageId);
cachedPackages.remove(packageId);
}
@@ -316,4 +329,4 @@ public void accept(Package aPackage) throws Exception {
});
}
-}
\ No newline at end of file
+}
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 0c947e7..b6d2b31 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
@@ -20,14 +20,11 @@
import android.support.annotation.Nullable;
import java.util.List;
-import java.util.concurrent.Callable;
import io.github.marktony.espresso.data.Company;
import io.github.marktony.espresso.data.source.CompaniesDataSource;
import io.github.marktony.espresso.realm.RealmHelper;
import io.reactivex.Observable;
-import io.reactivex.ObservableSource;
-import io.reactivex.functions.Function;
import io.realm.Case;
import io.realm.Realm;
import io.realm.Sort;
@@ -55,31 +52,18 @@ public static CompaniesLocalDataSource getInstance() {
@Override
public Observable> getCompanies() {
- return Observable.fromCallable(new Callable>() {
- @Override
- public List call() throws Exception {
- Realm rlm = RealmHelper.newRealmInstance();
- List companyList = rlm.copyFromRealm(rlm.where(Company.class)
- .findAllSorted("alphabet", Sort.ASCENDING));
- rlm.close();
- return companyList;
- }
- });
+ Realm rlm = RealmHelper.newRealmInstance();
+ return Observable
+ .fromIterable(rlm.copyFromRealm(rlm.where(Company.class).findAllSorted("alphabet", Sort.ASCENDING)))
+ .toList()
+ .toObservable();
}
@Override
- public Observable getCompany(@NonNull final String companyId) {
- return Observable.fromCallable(new Callable() {
- @Override
- public Company call() throws Exception {
- Realm rlm = RealmHelper.newRealmInstance();
- Company company = rlm.copyFromRealm(rlm.where(Company.class)
- .equalTo("id", companyId)
- .findFirst());
- rlm.close();
- return company;
- }
- });
+ public Observable getCompany(@NonNull String companyId) {
+ Realm rlm = RealmHelper.newRealmInstance();
+ return Observable
+ .just(rlm.copyFromRealm(rlm.where(Company.class).equalTo("id", companyId).findFirst()));
}
@Override
@@ -734,17 +718,11 @@ public void initData() {
}
@Override
- public Observable> searchCompanies(@NonNull final String keyWords) {
-
- return Observable.fromCallable(new Callable>() {
- @Override
- public List call() throws Exception {
- Realm rlm = RealmHelper.newRealmInstance();
- List companies = rlm.copyFromRealm(rlm.where(Company.class)
- .like(
- "name",
- "*" + keyWords + "*",
- Case.INSENSITIVE)
+ public Observable> searchCompanies(@NonNull String keyWords) {
+ Realm rlm = RealmHelper.newRealmInstance();
+ List results = rlm.copyFromRealm(
+ rlm.where(Company.class)
+ .like("name","*" + keyWords + "*", Case.INSENSITIVE)
.or()
.like("tel", "*" + keyWords + "*", Case.INSENSITIVE)
.or()
@@ -752,10 +730,9 @@ public List call() throws Exception {
.or()
.like("alphabet", "*" + keyWords + "*", Case.INSENSITIVE)
.findAllSorted("alphabet", Sort.ASCENDING));
- rlm.close();
- return companies;
- }
- });
+ return Observable.fromIterable(results)
+ .toList()
+ .toObservable();
}
}
\ No newline at end of file
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 c2e220f..e646803 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
@@ -20,7 +20,6 @@
import android.support.annotation.Nullable;
import java.util.List;
-import java.util.concurrent.Callable;
import io.github.marktony.espresso.data.Package;
import io.github.marktony.espresso.data.source.PackagesDataSource;
@@ -65,16 +64,10 @@ public static void destroyInstance() {
*/
@Override
public Observable> getPackages() {
- return Observable.fromCallable(new Callable>() {
- @Override
- public List call() throws Exception {
- Realm rlm = RealmHelper.newRealmInstance();
- List packageList = rlm.copyFromRealm(rlm.where(Package.class)
- .findAllSorted("timestamp", Sort.DESCENDING));
- rlm.close();
- return packageList;
- }
- });
+ Realm rlm = RealmHelper.newRealmInstance();
+
+ return Observable.just(rlm.copyFromRealm(rlm.where(Package.class)
+ .findAllSorted("timestamp", Sort.DESCENDING)));
}
/**
@@ -85,18 +78,11 @@ public List call() throws Exception {
* @return The observable package from database.
*/
@Override
- public Observable getPackage(@NonNull final String packNumber) {
- return Observable.fromCallable(new Callable() {
- @Override
- public Package call() throws Exception {
- Realm rlm = RealmHelper.newRealmInstance();
- Package aPackage = rlm.copyFromRealm(rlm.where(Package.class)
- .equalTo("number", packNumber)
- .findFirst());
- rlm.close();
- return aPackage;
- }
- });
+ public Observable getPackage(@NonNull String packNumber) {
+ Realm rlm = RealmHelper.newRealmInstance();
+ return Observable.just(rlm.copyFromRealm(rlm.where(Package.class)
+ .equalTo("number", packNumber)
+ .findFirst()));
}
/**
@@ -201,7 +187,6 @@ public boolean isPackageExist(@NonNull String packageId) {
RealmResults results = rlm.where(Package.class)
.equalTo("number", packageId)
.findAll();
- rlm.close();
return (results != null) && (!results.isEmpty());
}
@@ -221,32 +206,20 @@ public void updatePackageName(@NonNull String packageId, @NonNull String name) {
}
@Override
- public Observable> searchPackages(@NonNull
- final String keyWords) {
-
- return Observable.fromCallable(new Callable>() {
- @Override
- public List call() throws Exception {
- Realm rlm = RealmHelper.newRealmInstance();
- List packages = rlm.copyFromRealm(rlm.where(Package.class)
- .like(
- "name",
- "*" + keyWords + "*",
- Case.INSENSITIVE)
+ 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()
- .like(
- "company",
- "*" + keyWords + "*",
- Case.INSENSITIVE)
+ .like("company", "*" + keyWords + "*", Case.INSENSITIVE)
.or()
.like("number", "*" + keyWords + "*", Case.INSENSITIVE)
- .findAll());
- rlm.close();
- return packages;
- }
- });
+ .findAll()))
+ .toList()
+ .toObservable();
}
}
diff --git a/mobile/src/main/java/io/github/marktony/espresso/data/source/remote/PackagesRemoteDataSource.java b/mobile/src/main/java/io/github/marktony/espresso/data/source/remote/PackagesRemoteDataSource.java
index 654004d..82a2e72 100644
--- a/mobile/src/main/java/io/github/marktony/espresso/data/source/remote/PackagesRemoteDataSource.java
+++ b/mobile/src/main/java/io/github/marktony/espresso/data/source/remote/PackagesRemoteDataSource.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright(c) 2017 lizhaotailang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package io.github.marktony.espresso.data.source.remote;
import android.support.annotation.NonNull;
@@ -7,7 +23,6 @@
import io.github.marktony.espresso.data.Package;
import io.github.marktony.espresso.data.source.PackagesDataSource;
-import io.github.marktony.espresso.realm.RealmHelper;
import io.github.marktony.espresso.retrofit.RetrofitClient;
import io.github.marktony.espresso.retrofit.RetrofitService;
import io.reactivex.Observable;
@@ -19,6 +34,8 @@
import io.realm.Realm;
import io.realm.RealmConfiguration;
+import static io.github.marktony.espresso.realm.RealmHelper.DATABASE_NAME;
+
/**
* Created by lizhaotailang on 2017/3/7.
* Implementation of the data source that adds a latency simulating network.
@@ -81,7 +98,10 @@ public void deletePackage(@NonNull String packageId) {
public Observable> refreshPackages() {
// It is necessary to build a new realm instance
// in a different thread.
- Realm realm = RealmHelper.newRealmInstance();
+ Realm realm = Realm.getInstance(new RealmConfiguration.Builder()
+ .deleteRealmIfMigrationNeeded()
+ .name(DATABASE_NAME)
+ .build());
return Observable.fromIterable(realm.copyFromRealm(realm.where(Package.class).findAll()))
.subscribeOn(Schedulers.io())
@@ -105,7 +125,10 @@ public ObservableSource apply(Package aPackage) throws Exception {
public Observable refreshPackage(@NonNull String packageId) {
// It is necessary to build a new realm instance
// in a different thread.
- Realm realm = RealmHelper.newRealmInstance();
+ Realm realm = Realm.getInstance(new RealmConfiguration.Builder()
+ .deleteRealmIfMigrationNeeded()
+ .name(DATABASE_NAME)
+ .build());
// Set a copy rather than use the raw data.
final Package p = realm.copyFromRealm(realm.where(Package.class)
.equalTo("number", packageId)
@@ -131,7 +154,10 @@ public void accept(Package aPackage) throws Exception {
if (aPackage != null && aPackage.getData() != null) {
// It is necessary to build a new realm instance
// in a different thread.
- Realm rlm = RealmHelper.newRealmInstance();
+ Realm rlm = Realm.getInstance(new RealmConfiguration.Builder()
+ .deleteRealmIfMigrationNeeded()
+ .name(DATABASE_NAME)
+ .build());
// Only when the origin data is null or the origin
// data's size is less than the latest data's size
diff --git a/mobile/src/main/java/io/github/marktony/espresso/mvp/addpackage/AddPackageFragment.java b/mobile/src/main/java/io/github/marktony/espresso/mvp/addpackage/AddPackageFragment.java
index d91bb9d..3abacf1 100644
--- a/mobile/src/main/java/io/github/marktony/espresso/mvp/addpackage/AddPackageFragment.java
+++ b/mobile/src/main/java/io/github/marktony/espresso/mvp/addpackage/AddPackageFragment.java
@@ -23,6 +23,7 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
@@ -33,6 +34,7 @@
import android.support.design.widget.TextInputEditText;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
+import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.AppCompatTextView;
import android.support.v7.widget.Toolbar;
@@ -40,6 +42,7 @@
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;
import android.widget.ProgressBar;
@@ -67,6 +70,7 @@ public class AddPackageFragment extends Fragment
private AppCompatTextView textViewScanCode;
private FloatingActionButton fab;
private ProgressBar progressBar;
+ private NestedScrollView scrollView;
private AddPackageContract.Presenter presenter;
@@ -95,6 +99,8 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
initViews(view);
+ addLayoutListener(scrollView, editTextName);
+
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -160,6 +166,32 @@ public void onPause() {
presenter.unsubscribe();
}
+ /**
+ * Scroll the screen to avoid edit text being covered by imm such as the soft keyboard.
+ * It is better to set the height as 150 because some devices
+ * has the navigation bar. The height 100 might not trigger the scrolling action.
+ * @param main The scroll view.
+ * @param scroll The view to show.
+ */
+ private void addLayoutListener(final View main, final View scroll) {
+ main.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ Rect rect = new Rect();
+ main.getWindowVisibleDisplayFrame(rect);
+ int mainInvisibleHeight = main.getRootView().getHeight() - rect.bottom;
+ if (mainInvisibleHeight > 150) {
+ int[] location = new int[2];
+ scroll.getLocationInWindow(location);
+ int scrollHeight = (location[1] + scroll.getHeight()) - rect.bottom;
+ main.scrollTo(0, scrollHeight);
+ } else {
+ main.scrollTo(0, 0);
+ }
+ }
+ });
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
@@ -185,6 +217,8 @@ public void initViews(View view) {
textViewScanCode = (AppCompatTextView) view.findViewById(R.id.textViewScanCode);
fab = (FloatingActionButton) view.findViewById(R.id.fab);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
+ scrollView = (NestedScrollView) view.findViewById(R.id.scrollView);
+
}
/**
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 cd13200..f3a09da 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
@@ -155,7 +155,7 @@ private void updateIndicators(int position) {
}
}
- private Handler handler = new Handler() {
+ private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
diff --git a/mobile/src/main/java/io/github/marktony/espresso/zxing/utils/InactivityTimer.java b/mobile/src/main/java/io/github/marktony/espresso/zxing/utils/InactivityTimer.java
index 3aad2cb..106b04d 100644
--- a/mobile/src/main/java/io/github/marktony/espresso/zxing/utils/InactivityTimer.java
+++ b/mobile/src/main/java/io/github/marktony/espresso/zxing/utils/InactivityTimer.java
@@ -24,7 +24,6 @@
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.BatteryManager;
-import android.os.Build;
import android.util.Log;
/**