this commit improves error messages and close #97

This commit is contained in:
Kosh 2017-03-18 16:06:56 +08:00
parent a22cc8f8a6
commit 42a4b4df94
8 changed files with 209 additions and 33 deletions

View File

@ -79,4 +79,23 @@
-keepclassmembers class com.prettifier.pretty.callback.MarkDownInterceptorInterface {
public *;
}
#-keep class com.siimkinks.sqlitemagic.** {*;}
-dontwarn java.lang.FunctionalInterface
-dontwarn java.util.**
-dontwarn java.time.**
-dontwarn javax.annotation.**
-dontwarn javax.cache.**
-dontwarn javax.naming.**
-dontwarn javax.transaction.**
-dontwarn java.sql.**
-dontwarn android.support.**
-dontwarn io.requery.cache.**
-dontwarn io.requery.rx.**
-dontwarn io.requery.reactivex.**
-dontwarn io.requery.reactor.**
-dontwarn io.requery.query.**
-dontwarn io.requery.android.sqlcipher.**
-dontwarn io.requery.android.sqlitex.**
-keepclassmembers enum io.requery.** {
public static **[] values();
public static ** valueOf(java.lang.String);
}

View File

@ -45,7 +45,7 @@ public class App extends MultiDexApplication {
public SingleEntityStore<Persistable> getDataStore() {
if (dataStore == null) {
EntityModel model = Models.DEFAULT;
DatabaseSource source = new DatabaseSource(this, model, "FastHub-DB", 2);
DatabaseSource source = new DatabaseSource(this, model, "FastHub-DB", 1);
Configuration configuration = new ConfigurationBuilder(source, model)
.useDefaultLogging()
.build();

View File

@ -6,33 +6,33 @@ import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fastaccess.App;
import com.fastaccess.BuildConfig;
import com.fastaccess.R;
import com.fastaccess.data.service.LoginRestService;
import com.fastaccess.data.dao.GitHubErrorResponse;
import com.fastaccess.data.service.GistService;
import com.fastaccess.data.service.IssueService;
import com.fastaccess.data.service.LoginRestService;
import com.fastaccess.data.service.NotificationService;
import com.fastaccess.data.service.PullRequestService;
import com.fastaccess.data.service.RepoService;
import com.fastaccess.data.service.SearchService;
import com.fastaccess.data.service.UserRestService;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.Logger;
import com.fastaccess.helper.PrefGetter;
import com.fastaccess.provider.rest.converters.GithubResponseConverter;
import com.fastaccess.provider.rest.handler.RetrofitException;
import com.fastaccess.provider.rest.handler.RxErrorHandlingCallAdapterFactory;
import com.fastaccess.provider.rest.interceptors.PaginationInterceptor;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.lang.reflect.Modifier;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.HttpException;
@ -55,14 +55,6 @@ public class RestProvider {
.setPrettyPrinting()
.create();
private static Cache provideCache() {
if (cache == null) {
int cacheSize = 20 * 1024 * 1024; //20MB
cache = new Cache(App.getInstance().getCacheDir(), cacheSize);
}
return cache;
}
private static OkHttpClient provideOkHttpClient(boolean forLogin) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
if (BuildConfig.DEBUG) {
@ -87,7 +79,6 @@ public class RestProvider {
Request request = requestBuilder.build();
return chain.proceed(request);
});
// client.cache(provideCache());//disable cache, since we are going offline.
return client.build();
}
@ -96,18 +87,18 @@ public class RestProvider {
.baseUrl(BuildConfig.REST_URL)
.client(provideOkHttpClient(false))
.addConverterFactory(new GithubResponseConverter(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
.build();
}
public static long downloadFile(@NonNull Context context, @NonNull String url) {
public static void downloadFile(@NonNull Context context, @NonNull String url) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription(url);
request.setTitle(context.getString(R.string.downloading_file));
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
return downloadManager.enqueue(request);
downloadManager.enqueue(request);
}
public static int getErrorCode(Throwable throwable) {
@ -157,14 +148,11 @@ public class RestProvider {
}
@Nullable public static GitHubErrorResponse getErrorResponse(@NonNull Throwable throwable) {
if (throwable instanceof HttpException) {
ResponseBody body = ((HttpException) throwable).response().errorBody();
if (body != null) {
try {
Logger.e(body.string());
return new Gson().fromJson(body.toString(), GitHubErrorResponse.class);
} catch (Exception ignored) {}
}
RetrofitException error = (RetrofitException) throwable;
try {
return error.getErrorBodyAs(GitHubErrorResponse.class);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

View File

@ -0,0 +1,88 @@
package com.fastaccess.provider.rest.handler;
import java.io.IOException;
import java.lang.annotation.Annotation;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Response;
import retrofit2.Retrofit;
/**
* copied from http://bytes.babbel.com/en/articles/2016-03-16-retrofit2-rxjava-error-handling.html
*/
public class RetrofitException extends RuntimeException {
public static RetrofitException httpError(String url, Response response, Retrofit retrofit) {
String message = response.code() + " " + response.message();
return new RetrofitException(message, url, response, Kind.HTTP, null, retrofit);
}
public static RetrofitException networkError(IOException exception) {
return new RetrofitException(exception.getMessage(), null, null, Kind.NETWORK, exception, null);
}
public static RetrofitException unexpectedError(Throwable exception) {
return new RetrofitException(exception.getMessage(), null, null, Kind.UNEXPECTED, exception, null);
}
/** Identifies the event kind which triggered a {@link RetrofitException}. */
public enum Kind {
/** An {@link IOException} occurred while communicating to the server. */
NETWORK,
/** A non-200 HTTP status code was received from the server. */
HTTP,
/**
* An internal error occurred while attempting to execute a request. It is best practice to
* re-throw this exception so your application crashes.
*/
UNEXPECTED
}
private final String url;
private final Response response;
private final Kind kind;
private final Retrofit retrofit;
public RetrofitException(String message, String url, Response response, Kind kind, Throwable exception, Retrofit retrofit) {
super(message, exception);
this.url = url;
this.response = response;
this.kind = kind;
this.retrofit = retrofit;
}
/** The request URL which produced the error. */
public String getUrl() {
return url;
}
/** Response object containing status code, headers, body, etc. */
public Response getResponse() {
return response;
}
/** The event kind which triggered this error. */
public Kind getKind() {
return kind;
}
/** The Retrofit this request was executed on */
public Retrofit getRetrofit() {
return retrofit;
}
/**
* HTTP response body converted to specified {@code type}. {@code null} if there is no
* response.
*
* @throws IOException
* if unable to convert the body to the specified {@code type}.
*/
public <T> T getErrorBodyAs(Class<T> type) throws IOException {
if (response == null || response.errorBody() == null) {
return null;
}
Converter<ResponseBody, T> converter = retrofit.responseBodyConverter(type, new Annotation[0]);
return converter.convert(response.errorBody());
}
}

View File

@ -0,0 +1,67 @@
package com.fastaccess.provider.rest.handler;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.HttpException;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import rx.Observable;
import rx.functions.Func1;
/**
* copied from http://bytes.babbel.com/en/articles/2016-03-16-retrofit2-rxjava-error-handling.html
*/
public class RxErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
private final RxJavaCallAdapterFactory original;
private RxErrorHandlingCallAdapterFactory() {
original = RxJavaCallAdapterFactory.create();
}
@Override public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new RxCallAdapterWrapper(retrofit, original.get(returnType, annotations, retrofit));
}
public static CallAdapter.Factory create() {
return new RxErrorHandlingCallAdapterFactory();
}
private static class RxCallAdapterWrapper implements CallAdapter<Observable<?>> {
private final Retrofit retrofit;
private final CallAdapter<?> wrapped;
public RxCallAdapterWrapper(Retrofit retrofit, CallAdapter<?> wrapped) {
this.retrofit = retrofit;
this.wrapped = wrapped;
}
@Override public Type responseType() {
return wrapped.responseType();
}
@SuppressWarnings("unchecked") @Override public <R> Observable<?> adapt(Call<R> call) {
return ((Observable) wrapped.adapt(call)).onErrorResumeNext(new Func1<Throwable, Observable>() {
@Override public Observable call(Throwable throwable) {
return Observable.error(asRetrofitException(throwable));
}
});
}
private RetrofitException asRetrofitException(Throwable throwable) {
if (throwable instanceof HttpException) {
HttpException httpException = (HttpException) throwable;
Response response = httpException.response();
return RetrofitException.httpError(response.raw().request().url().toString(), response, retrofit);
}
if (throwable instanceof IOException) {
return RetrofitException.networkError((IOException) throwable);
}
return RetrofitException.unexpectedError(throwable);
}
}
}

View File

@ -147,10 +147,9 @@ public abstract class BaseActivity<V extends BaseMvp.FAView, P extends BasePrese
hideProgress();
if (toast != null) toast.cancel();
toast = titleRes.equals(getString(R.string.error))
? Toasty.warning(getApplicationContext(), msgRes, Toast.LENGTH_LONG)
? Toasty.error(getApplicationContext(), msgRes, Toast.LENGTH_LONG)
: Toasty.info(getApplicationContext(), msgRes, Toast.LENGTH_LONG);
toast.show();
}
@Override public void showErrorMessage(@NonNull String msgRes) {

View File

@ -6,9 +6,9 @@ import android.support.annotation.StringRes;
import com.fastaccess.R;
import com.fastaccess.data.dao.GitHubErrorResponse;
import com.fastaccess.helper.Logger;
import com.fastaccess.helper.RxHelper;
import com.fastaccess.provider.rest.RestProvider;
import com.fastaccess.provider.rest.handler.RetrofitException;
import com.fastaccess.ui.base.mvp.BaseMvp;
import net.grandcentrix.thirtyinch.TiPresenter;
@ -47,11 +47,10 @@ public class BasePresenter<V extends BaseMvp.FAView> extends TiPresenter<V> impl
return;
}
GitHubErrorResponse errorResponse = RestProvider.getErrorResponse(throwable);
Logger.e(errorResponse);
if (errorResponse != null && errorResponse.getMessage() != null) {
sendToView(v -> v.showErrorMessage(errorResponse.getMessage()));
} else {
sendToView(v -> v.showErrorMessage(throwable.getMessage()));
sendToView(v -> v.showMessage(R.string.error, getPrettifiedErrorMessage(throwable)));
}
}
@ -64,6 +63,23 @@ public class BasePresenter<V extends BaseMvp.FAView> extends TiPresenter<V> impl
}
@StringRes private int getPrettifiedErrorMessage(@Nullable Throwable throwable) {
return 0;
int resId = R.string.network_error;
RetrofitException exception = (RetrofitException) throwable;
if (exception != null) {
if (exception.getKind() != null) {
switch (exception.getKind()) {
case NETWORK:
resId = R.string.network_error;
break;
case HTTP:
resId = R.string.request_error;
break;
case UNEXPECTED:
resId = R.string.unexpected_error;
break;
}
}
}
return resId;
}
}

View File

@ -89,7 +89,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="@dimen/spacing_normal"
android:visibility="gone"
tools:text="Java"
tools:visibility="visible"/>