Reimplemented API Provider

To try to fix NullPointerException on mApi reported in Play Store
This commit is contained in:
Daniele Verducci (Slimpenguin) 2022-02-20 09:27:23 +01:00
parent 713e47b20a
commit 4f59359f5e
11 changed files with 56 additions and 78 deletions

View File

@ -18,12 +18,12 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 30 compileSdkVersion 31
defaultConfig { defaultConfig {
applicationId "it.danieleverducci.nextcloudmaps" applicationId "it.danieleverducci.nextcloudmaps"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 30 targetSdkVersion 31
versionCode 6 versionCode 6
versionName "0.3.4" versionName "0.3.4"
@ -54,7 +54,7 @@ repositories {
dependencies { dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"]) implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'com.android.support:design:30.0.1' implementation 'com.android.support:design:31.0.0'
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation "androidx.cardview:cardview:1.0.0" implementation "androidx.cardview:cardview:1.0.0"
@ -70,7 +70,7 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.6.1' implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
// Nextcloud SSO // Nextcloud SSO
implementation "com.github.nextcloud:Android-SingleSignOn:0.5.6" implementation "com.github.nextcloud:Android-SingleSignOn:0.6.1"
// OSMDroid // OSMDroid
implementation 'org.osmdroid:osmdroid-android:6.1.10' implementation 'org.osmdroid:osmdroid-android:6.1.10'

View File

@ -35,21 +35,24 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity android:name=".activity.login.LoginActivity"> <activity android:name=".activity.login.LoginActivity"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".activity.main.MainActivity"> <activity android:name=".activity.main.MainActivity"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".activity.detail.GeofavoriteDetailActivity"> android:name=".activity.detail.GeofavoriteDetailActivity"
android:exported="true">
<!-- standard "geo" scheme --> <!-- standard "geo" scheme -->
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW"/> <action android:name="android.intent.action.VIEW"/>
@ -89,6 +92,7 @@
</activity> </activity>
<activity android:name=".activity.mappicker.MapPickerActivity" <activity android:name=".activity.mappicker.MapPickerActivity"
android:exported="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />

View File

@ -119,7 +119,7 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
}); });
mViewModel = new ViewModelProvider(this).get(GeofavoriteDetailActivityViewModel.class); mViewModel = new ViewModelProvider(this).get(GeofavoriteDetailActivityViewModel.class);
mViewModel.init(); mViewModel.init(getApplicationContext());
mViewModel.getCategories().observe(this, new Observer<HashSet<String>>() { mViewModel.getCategories().observe(this, new Observer<HashSet<String>>() {
@Override @Override
public void onChanged(HashSet<String> categories) { public void onChanged(HashSet<String> categories) {

View File

@ -1,5 +1,7 @@
package it.danieleverducci.nextcloudmaps.activity.detail; package it.danieleverducci.nextcloudmaps.activity.detail;
import android.content.Context;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
@ -14,8 +16,8 @@ import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
public class GeofavoriteDetailActivityViewModel extends ViewModel { public class GeofavoriteDetailActivityViewModel extends ViewModel {
private GeofavoriteRepository mRepo; private GeofavoriteRepository mRepo;
public void init() { public void init(Context applicationContext) {
mRepo = GeofavoriteRepository.getInstance(); mRepo = GeofavoriteRepository.getInstance(applicationContext);
} }
public Geofavorite getGeofavorite(int id) { public Geofavorite getGeofavorite(int id) {

View File

@ -41,11 +41,11 @@ import com.nextcloud.android.sso.ui.UiExceptionManager;
import it.danieleverducci.nextcloudmaps.R; import it.danieleverducci.nextcloudmaps.R;
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity; import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
import it.danieleverducci.nextcloudmaps.activity.main.MainActivity; import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
import it.danieleverducci.nextcloudmaps.api.API;
import it.danieleverducci.nextcloudmaps.api.ApiProvider; import it.danieleverducci.nextcloudmaps.api.ApiProvider;
public class LoginActivity extends NextcloudMapsStyledActivity { public class LoginActivity extends NextcloudMapsStyledActivity {
protected ApiProvider mApi;
protected ProgressBar progress; protected ProgressBar progress;
protected Button button; protected Button button;
@ -115,9 +115,6 @@ public class LoginActivity extends NextcloudMapsStyledActivity {
} }
private void accountAccessDone() { private void accountAccessDone() {
Context l_context = getApplicationContext();
mApi = new ApiProvider(l_context);
Intent intent = new Intent(LoginActivity.this, MainActivity.class); Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent); startActivity(intent);

View File

@ -58,6 +58,7 @@ import it.danieleverducci.nextcloudmaps.activity.login.LoginActivity;
import it.danieleverducci.nextcloudmaps.activity.main.NavigationAdapter.NavigationItem; import it.danieleverducci.nextcloudmaps.activity.main.NavigationAdapter.NavigationItem;
import it.danieleverducci.nextcloudmaps.activity.main.SortingOrderDialogFragment.OnSortingOrderListener; import it.danieleverducci.nextcloudmaps.activity.main.SortingOrderDialogFragment.OnSortingOrderListener;
import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity; import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity;
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
import it.danieleverducci.nextcloudmaps.model.Geofavorite; import it.danieleverducci.nextcloudmaps.model.Geofavorite;
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser; import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
import it.danieleverducci.nextcloudmaps.utils.IntentGenerator; import it.danieleverducci.nextcloudmaps.utils.IntentGenerator;
@ -140,7 +141,7 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
mMainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class); mMainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
mMainActivityViewModel.init(); mMainActivityViewModel.init(getApplicationContext());
mMainActivityViewModel.getIsUpdating().observe(this, new Observer<Boolean>() { mMainActivityViewModel.getIsUpdating().observe(this, new Observer<Boolean>() {
@Override @Override
public void onChanged(@Nullable Boolean aBoolean) { public void onChanged(@Nullable Boolean aBoolean) {
@ -155,7 +156,7 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
mMainActivityViewModel.getOnFinished().observe(this, new Observer<Boolean>() { mMainActivityViewModel.getOnFinished().observe(this, new Observer<Boolean>() {
@Override @Override
public void onChanged(@Nullable Boolean success) { public void onChanged(@Nullable Boolean success) {
if(!success){ if(success == null || !success){
Toast.makeText(MainActivity.this, R.string.list_geofavorite_connection_error, Toast.LENGTH_LONG).show(); Toast.makeText(MainActivity.this, R.string.list_geofavorite_connection_error, Toast.LENGTH_LONG).show();
} }
} }
@ -297,9 +298,11 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
} }
private void switch_account() { private void switch_account() {
ApiProvider.logout();
SingleAccountHelper.setCurrentAccount(this, null); SingleAccountHelper.setCurrentAccount(this, null);
Intent intent = new Intent(MainActivity.this, LoginActivity.class); Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent); startActivity(intent);
finish();
} }
@Override @Override

View File

@ -1,5 +1,7 @@
package it.danieleverducci.nextcloudmaps.activity.main; package it.danieleverducci.nextcloudmaps.activity.main;
import android.content.Context;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
@ -12,8 +14,8 @@ import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
public class MainActivityViewModel extends ViewModel { public class MainActivityViewModel extends ViewModel {
private GeofavoriteRepository mRepo; private GeofavoriteRepository mRepo;
public void init() { public void init(Context applicationContext) {
mRepo = GeofavoriteRepository.getInstance(); mRepo = GeofavoriteRepository.getInstance(applicationContext);
} }
public LiveData<List<Geofavorite>> getGeofavorites(){ public LiveData<List<Geofavorite>> getGeofavorites(){

View File

@ -24,6 +24,7 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.nextcloud.android.sso.api.NextcloudAPI; import com.nextcloud.android.sso.api.NextcloudAPI;
@ -35,47 +36,27 @@ import com.nextcloud.android.sso.model.SingleSignOnAccount;
import retrofit2.NextcloudRetrofitApiBuilder; import retrofit2.NextcloudRetrofitApiBuilder;
public class ApiProvider { public class ApiProvider {
private final String TAG = ApiProvider.class.getCanonicalName(); private static final String TAG = ApiProvider.class.getCanonicalName();
@NonNull
protected Context context;
protected static API mApi; protected static API mApi;
protected static String ssoAccountName; @Nullable
public static API getAPI(Context context) {
public ApiProvider(Context context) { if (mApi == null) {
this.context = context;
initSsoApi(new NextcloudAPI.ApiConnectedListener() {
@Override
public void onConnected() {
Log.d(TAG, "Connected to Nextcloud instance");
}
@Override
public void onError(Exception ex) {
Log.d(TAG, "Unable to connect to Nextcloud instance: " + ex.toString());
}
});
}
public void initSsoApi(final NextcloudAPI.ApiConnectedListener callback) {
try { try {
SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context); SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), callback); NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create());
ssoAccountName = ssoAccount.name;
mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class); mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class);
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) { } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
Log.d(TAG, "setAccout() called with: ex = [" + e + "]"); Log.d(TAG, "setAccout() called with: ex = [" + e + "]");
} }
} }
public static API getAPI() {
return mApi; return mApi;
} }
public static String getAccountName() { public static void logout() {
return ssoAccountName; mApi = null;
} }
} }

View File

@ -1,9 +1,9 @@
package it.danieleverducci.nextcloudmaps.repository; package it.danieleverducci.nextcloudmaps.repository;
import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import java.util.ArrayList; import java.util.ArrayList;
@ -29,9 +29,15 @@ public class GeofavoriteRepository {
private MutableLiveData<Boolean> mIsUpdating = new MutableLiveData<>(false); private MutableLiveData<Boolean> mIsUpdating = new MutableLiveData<>(false);
private SingleLiveEvent<Boolean> mOnFinished = new SingleLiveEvent<>(); private SingleLiveEvent<Boolean> mOnFinished = new SingleLiveEvent<>();
public static GeofavoriteRepository getInstance() { private Context applicationContext;
public GeofavoriteRepository(Context applicationContext) {
this.applicationContext = applicationContext;
}
public static GeofavoriteRepository getInstance(Context applicationContext) {
if(instance == null){ if(instance == null){
instance = new GeofavoriteRepository(); instance = new GeofavoriteRepository(applicationContext);
} }
return instance; return instance;
} }
@ -59,7 +65,7 @@ public class GeofavoriteRepository {
public void updateGeofavorites() { public void updateGeofavorites() {
mIsUpdating.postValue(true); mIsUpdating.postValue(true);
// Obtain geofavorites // Obtain geofavorites
Call<List<Geofavorite>> call = ApiProvider.getAPI().getGeofavorites(); Call<List<Geofavorite>> call = ApiProvider.getAPI(this.applicationContext).getGeofavorites();
call.enqueue(new Callback<List<Geofavorite>>() { call.enqueue(new Callback<List<Geofavorite>>() {
@Override @Override
public void onResponse(@NonNull Call<List<Geofavorite>> call, @NonNull Response<List<Geofavorite>> response) { public void onResponse(@NonNull Call<List<Geofavorite>> call, @NonNull Response<List<Geofavorite>> response) {
@ -94,10 +100,10 @@ public class GeofavoriteRepository {
Call<Geofavorite> call; Call<Geofavorite> call;
if (geofav.getId() == 0) { if (geofav.getId() == 0) {
// New geofavorite // New geofavorite
call = ApiProvider.getAPI().createGeofavorite(geofav); call = ApiProvider.getAPI(this.applicationContext).createGeofavorite(geofav);
} else { } else {
// Update existing geofavorite // Update existing geofavorite
call = ApiProvider.getAPI().updateGeofavorite(geofav.getId(), geofav); call = ApiProvider.getAPI(this.applicationContext).updateGeofavorite(geofav.getId(), geofav);
} }
call.enqueue(new Callback<Geofavorite>() { call.enqueue(new Callback<Geofavorite>() {
@Override @Override
@ -129,7 +135,7 @@ public class GeofavoriteRepository {
public void deleteGeofavorite(Geofavorite geofav) { public void deleteGeofavorite(Geofavorite geofav) {
mIsUpdating.postValue(true); mIsUpdating.postValue(true);
// Delete Geofavorite // Delete Geofavorite
Call<Geofavorite> call = ApiProvider.getAPI().deleteGeofavorite(geofav.getId()); Call<Geofavorite> call = ApiProvider.getAPI(this.applicationContext).deleteGeofavorite(geofav.getId());
call.enqueue(new Callback<Geofavorite>() { call.enqueue(new Callback<Geofavorite>() {
@Override @Override
public void onResponse(Call<Geofavorite> call, Response<Geofavorite> response) { public void onResponse(Call<Geofavorite> call, Response<Geofavorite> response) {

View File

@ -25,7 +25,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.2.2' classpath 'com.android.tools.build:gradle:7.1.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View File

@ -1,23 +1,6 @@
# #Sun Feb 20 08:50:37 CET 2022
# Nextcloud Geofavorites for Android
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#Mon Oct 05 23:27:18 ART 2020
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip zipStoreBase=GRADLE_USER_HOME