gegham commented 4 years ago
Review
Why is the LoginActivity.LOADING_TAG used here?
implement_add_device_functionality
into dev
4 years ago
@@ -38,6 +38,9 @@ buildscript { | |||
constraintlayoutVersion = '1.1.3' | |||
lifecycleExtensionVersion = '2.2.0' | |||
lifecycleViewModelVersion = '2.2.0' | |||
rxandroidVersion = '2.0.1' | |||
rxjavaVersion = '2.1.6' | |||
adapterrxjava2Version = '2.3.0' | |||
groupName = 'com.wireguard.android' | |||
} | |||
@@ -90,6 +90,10 @@ dependencies { | |||
implementation "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion" | |||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionVersion" | |||
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycleViewModelVersion" | |||
//RxJava | |||
implementation "io.reactivex.rxjava2:rxandroid:$rxandroidVersion" | |||
implementation "io.reactivex.rxjava2:rxjava:$rxjavaVersion" | |||
implementation "com.squareup.retrofit2:adapter-rxjava2:$adapterrxjava2Version" | |||
} | |||
tasks.withType(JavaCompile) { | |||
@@ -72,7 +72,6 @@ | |||
<action android:name="android.intent.action.MAIN" /> | |||
</intent-filter> | |||
</activity> | |||
<provider | |||
|
|||
android:name=".activity.LogViewerActivity$ExportedLogContentProvider" | |||
android:authorities="${applicationId}.exported-log" | |||
@@ -0,0 +1,61 @@ | |||
package com.wireguard.android.activity; | |||
import android.os.Bundle; | |||
import android.os.Handler; | |||
import com.wireguard.android.fragment.LoadingDialogFragment; | |||
import androidx.annotation.Nullable; | |||
import androidx.appcompat.app.AppCompatActivity; | |||
import androidx.lifecycle.Lifecycle; | |||
public class BaseActivityBubble extends AppCompatActivity { | |||
public static final String LOADING_TAG = "loading_tag"; | |||
public static final String NO_CONNECTION_TAG = "no_connection_tag"; | |||
public static final String RATE_TAG = "rate tag"; | |||
private final long LOADER_DELAY = 1000; | |||
private LoadingDialogFragment loadingDialog; | |||
private boolean showDialog = true; | |||
@Override | |||
protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
super.onCreate(savedInstanceState); | |||
} | |||
public void showLoadingDialog() { | |||
showDialog = true; | |||
final Handler handler = new Handler(); | |||
handler.postDelayed(new Runnable() { | |||
@Override | |||
public void run() { | |||
if (showDialog) { | |||
if (loadingDialog == null | |||
|| loadingDialog.getDialog() == null | |||
|| !loadingDialog.getDialog().isShowing() | |||
|| loadingDialog.isRemoving()) { | |||
if (loadingDialog != null) { | |||
loadingDialog.dismissAllowingStateLoss(); | |||
} | |||
if (getLifecycle().getCurrentState() == Lifecycle.State.RESUMED) { | |||
loadingDialog = LoadingDialogFragment.newInstance(); | |||
getSupportFragmentManager().beginTransaction(). | |||
add(loadingDialog, LOADING_TAG).commitAllowingStateLoss(); | |||
} | |||
} | |||
} | |||
} | |||
}, LOADER_DELAY); | |||
} | |||
public void closeLoadingDialog() { | |||
showDialog = false; | |||
if (loadingDialog != null && loadingDialog.getDialog() != null | |||
&& loadingDialog.getDialog().isShowing() | |||
&& !loadingDialog.isRemoving()) { | |||
loadingDialog.dismissAllowingStateLoss(); | |||
} | |||
} | |||
} |
@@ -1,7 +1,5 @@ | |||
package com.wireguard.android.activity; | |||
import androidx.appcompat.app.AppCompatActivity; | |||
import androidx.lifecycle.Observer; | |||
import androidx.lifecycle.ViewModelProvider; | |||
import android.os.Bundle; | |||
@@ -12,14 +10,11 @@ import android.widget.Button; | |||
import android.widget.EditText; | |||
import android.widget.Toast; | |||
import com.wireguard.android.R; | |||
import com.wireguard.android.api.ApiConstants; | |||
import com.wireguard.android.model.User; | |||
import com.wireguard.android.resource.StatusResource; | |||
import com.wireguard.android.viewmodel.LoginViewModel; | |||
import java.util.HashMap; | |||
public class LoginActivity extends AppCompatActivity { | |||
public class LoginActivity extends BaseActivityBubble { | |||
private LoginViewModel loginViewModel; | |||
private EditText bubbleName; | |||
@@ -45,6 +40,7 @@ public class LoginActivity extends AppCompatActivity { | |||
@Override public void onClick(final View v) { | |||
final String username = userName.getText().toString().trim(); | |||
final String password = LoginActivity.this.password.getText().toString().trim(); | |||
showLoadingDialog(); | |||
login(username,password); | |||
} | |||
}); | |||
@@ -60,17 +56,19 @@ public class LoginActivity extends AppCompatActivity { | |||
private void login(String username, String password) { | |||
loginViewModel.login(username,password,this).observe(this, new Observer<StatusResource<User>>() { | |||
@Override public void onChanged(final StatusResource<User> userStatusResource) { | |||
switch (userStatusResource.status){ | |||
switch (userStatusResource.status) { | |||
case SUCCESS: | |||
Toast.makeText(LoginActivity.this,"Success",Toast.LENGTH_SHORT).show(); | |||
Log.d("TAG","Success"); | |||
Toast.makeText(LoginActivity.this, "Success", Toast.LENGTH_SHORT).show(); | |||
Log.d("TAG", "Success"); | |||
closeLoadingDialog(); | |||
break; | |||
case LOADING: | |||
Log.d("TAG","Loading"); | |||
Log.d("TAG", "Loading"); | |||
break; | |||
case ERROR: | |||
Toast.makeText(LoginActivity.this,"Login Failed",Toast.LENGTH_SHORT).show(); | |||
Log.d("TAG","Error"); | |||
closeLoadingDialog(); | |||
Toast.makeText(LoginActivity.this, "Login Failed", Toast.LENGTH_SHORT).show(); | |||
Log.d("TAG", "Error"); | |||
break; | |||
} | |||
} | |||
@@ -3,6 +3,11 @@ package com.wireguard.android.api; | |||
public class ApiConstants { | |||
public static final String BASE_URL = "https://jtest2.bubblesecure.com:1443/api/"; | |||
public static final String LOGIN_URL = "auth/login"; | |||
public static final String ALL_DEVICES_URL = "me/devices"; | |||
public static final String ADD_DEVICE_URL = "me/devices"; | |||
public static final String USERNAME = "username"; | |||
public static final String PASSWORD = "password"; | |||
public static final String AUTHORIZATION_HEADER = "X-Bubble-Session"; | |||
public static final String DEVICE_NAME = "name"; | |||
public static final String DEVICE_TYPE = "deviceType"; | |||
} |
@@ -1,13 +1,20 @@ | |||
package com.wireguard.android.api.network; | |||
import com.wireguard.android.api.ApiConstants; | |||
import com.wireguard.android.model.Device; | |||
import com.wireguard.android.model.User; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import io.reactivex.Single; | |||
import retrofit2.Call; | |||
import retrofit2.http.Body; | |||
import retrofit2.http.GET; | |||
import retrofit2.http.HeaderMap; | |||
import retrofit2.http.POST; | |||
import retrofit2.http.PUT; | |||
/** | |||
Interface for API Calls | |||
@@ -15,5 +22,11 @@ import retrofit2.http.POST; | |||
public interface ClientApi { | |||
@POST(ApiConstants.LOGIN_URL) | |||
Call<User> login(@Body HashMap<String,String> params); | |||
Single<User> login(@Body HashMap<String,String> params); | |||
@GET(ApiConstants.ALL_DEVICES_URL) | |||
Single<List<Device>> getAllDevices(@HeaderMap HashMap<String,String> header); | |||
@PUT(ApiConstants.ADD_DEVICE_URL) | |||
Single<Device> addDevice(@HeaderMap HashMap<String,String> header , @Body HashMap<String,String> body); | |||
} |
@@ -6,6 +6,7 @@ import com.wireguard.android.api.interceptor.UserAgentInterceptor; | |||
import okhttp3.OkHttpClient; | |||
import okhttp3.logging.HttpLoggingInterceptor; | |||
import retrofit2.Retrofit; | |||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; | |||
import retrofit2.converter.gson.GsonConverterFactory; | |||
public class ClientService { | |||
@@ -41,6 +42,7 @@ public class ClientService { | |||
return new Retrofit.Builder() | |||
.baseUrl(ApiConstants.BASE_URL) | |||
.addConverterFactory(GsonConverterFactory.create()) | |||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) | |||
.client(httpClient.build()) | |||
.build().create(ClientApi.class); | |||
} | |||
@@ -0,0 +1,57 @@ | |||
package com.wireguard.android.fragment; | |||
import android.app.Dialog; | |||
import android.graphics.PorterDuff; | |||
import android.os.Bundle; | |||
import android.view.LayoutInflater; | |||
import android.view.View; | |||
import android.view.ViewGroup; | |||
import android.widget.ProgressBar; | |||
import com.wireguard.android.R; | |||
import com.wireguard.android.activity.BaseActivityBubble; | |||
import com.wireguard.android.activity.LoginActivity; | |||
import androidx.annotation.NonNull; | |||
import androidx.annotation.Nullable; | |||
import androidx.core.content.ContextCompat; | |||
import androidx.fragment.app.DialogFragment; | |||
public class LoadingDialogFragment extends DialogFragment { | |||
private ProgressBar progressBar; | |||
public static LoadingDialogFragment newInstance() { | |||
LoadingDialogFragment fragment = new LoadingDialogFragment(); | |||
Bundle args = new Bundle(); | |||
fragment.setArguments(args); | |||
return fragment; | |||
} | |||
@NonNull | |||
@Override | |||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { | |||
final Dialog dialog = new Dialog(getActivity(), getTheme()) { | |||
@Override | |||
public void onBackPressed() { | |||
gegham commented 4 years ago
Review
Why is the LoginActivity.LOADING_TAG used here? Why is the LoginActivity.LOADING_TAG used here?
|
|||
if (getActivity().getSupportFragmentManager().findFragmentByTag(BaseActivityBubble.LOADING_TAG) != null) { | |||
getActivity().onBackPressed(); | |||
} | |||
super.onBackPressed(); | |||
} | |||
}; | |||
return dialog; | |||
} | |||
@Override | |||
public View onCreateView(LayoutInflater inflater, ViewGroup container, | |||
Bundle savedInstanceState) { | |||
return inflater.inflate(R.layout.fragment_loading_dialog, container, false); | |||
} | |||
@Override | |||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { | |||
super.onViewCreated(view, savedInstanceState); | |||
progressBar = view.findViewById(R.id.progress); | |||
progressBar.getIndeterminateDrawable().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorPrimaryDark), PorterDuff.Mode.SRC_IN); | |||
} | |||
} |
@@ -0,0 +1,106 @@ | |||
package com.wireguard.android.model; | |||
import com.google.gson.annotations.Expose; | |||
import com.google.gson.annotations.SerializedName; | |||
public class Device { | |||
@SerializedName("uuid") | |||
@Expose | |||
private String uuid; | |||
@SerializedName("related") | |||
@Expose | |||
private String related; | |||
@SerializedName("ctime") | |||
@Expose | |||
private long ctime; | |||
@SerializedName("name") | |||
@Expose | |||
private String name; | |||
@SerializedName("account") | |||
@Expose | |||
private String account; | |||
@SerializedName("deviceType") | |||
@Expose | |||
private String deviceType; | |||
@SerializedName("enabled") | |||
@Expose | |||
private boolean enabled; | |||
@SerializedName("network") | |||
@Expose | |||
private String network; | |||
@SerializedName("shortId") | |||
@Expose | |||
private String shortId; | |||
public void setUuid(final String uuid) { | |||
this.uuid = uuid; | |||
} | |||
public void setRelated(final String related) { | |||
this.related = related; | |||
} | |||
public void setCtime(final long ctime) { | |||
this.ctime = ctime; | |||
} | |||
public void setName(final String name) { | |||
this.name = name; | |||
} | |||
public void setAccount(final String account) { | |||
this.account = account; | |||
} | |||
public void setDeviceType(final String deviceType) { | |||
this.deviceType = deviceType; | |||
} | |||
public void setEnabled(final boolean enabled) { | |||
this.enabled = enabled; | |||
} | |||
public void setNetwork(final String network) { | |||
this.network = network; | |||
} | |||
public void setShortId(final String shortId) { | |||
this.shortId = shortId; | |||
} | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
public String getRelated() { | |||
return related; | |||
} | |||
public long getCtime() { | |||
return ctime; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public String getAccount() { | |||
return account; | |||
} | |||
public String getDeviceType() { | |||
return deviceType; | |||
} | |||
public boolean isEnabled() { | |||
return enabled; | |||
} | |||
public String getNetwork() { | |||
return network; | |||
} | |||
public String getShortId() { | |||
return shortId; | |||
} | |||
} |
@@ -1,30 +1,40 @@ | |||
package com.wireguard.android.repository; | |||
import android.content.Context; | |||
import android.os.Build; | |||
import android.provider.Settings; | |||
import android.provider.Settings.Secure; | |||
import com.wireguard.android.api.ApiConstants; | |||
import com.wireguard.android.api.network.ClientApi; | |||
import com.wireguard.android.api.network.ClientService; | |||
import com.wireguard.android.api.network.NetworkBoundStatusResource; | |||
import com.wireguard.android.model.Device; | |||
import com.wireguard.android.model.User; | |||
import com.wireguard.android.resource.StatusResource; | |||
import com.wireguard.android.util.UserStore; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import androidx.lifecycle.MutableLiveData; | |||
import io.reactivex.android.schedulers.AndroidSchedulers; | |||
import io.reactivex.disposables.CompositeDisposable; | |||
import io.reactivex.disposables.Disposable; | |||
import io.reactivex.schedulers.Schedulers; | |||
import retrofit2.Call; | |||
import retrofit2.Callback; | |||
import retrofit2.Response; | |||
public class DataRepository { | |||
private static volatile DataRepository instance; | |||
private ClientApi clientApi; | |||
private CompositeDisposable compositeDisposable; | |||
public static final String NO_INTERNET_CONNECTION = "no_internet_connection"; | |||
private static final String SEPARATOR = ":"; | |||
private static final String SPACE = " "; | |||
private static final int ANDROID_ID = 1; | |||
private DataRepository() | |||
{ | |||
private DataRepository() { | |||
clientApi = ClientService.getInstance().createClientApi(); | |||
compositeDisposable = new CompositeDisposable(); | |||
} | |||
public static void buildRepositoryInstance() { | |||
@@ -41,36 +51,163 @@ public class DataRepository { | |||
return instance; | |||
} | |||
public MutableLiveData<StatusResource<User>> login(String username,String password , Context context){ | |||
return new NetworkBoundStatusResource<User>(){ | |||
public MutableLiveData<StatusResource<User>> login(String username, String password, Context context) { | |||
return new NetworkBoundStatusResource<User>() { | |||
@Override protected void createCall() { | |||
HashMap<String,String> data = new HashMap<>(); | |||
data.put(ApiConstants.USERNAME,username); | |||
data.put(ApiConstants.PASSWORD,password); | |||
clientApi.login(data).enqueue(new Callback<User>() { | |||
@Override public void onResponse(final Call<User> call, final Response<User> response) { | |||
if(response.isSuccessful()) { | |||
String token = response.body().getToken(); | |||
UserStore.getInstance(context).setToken(token); | |||
setMutableLiveData(StatusResource.success()); | |||
HashMap<String, String> data = new HashMap<>(); | |||
data.put(ApiConstants.USERNAME, username); | |||
data.put(ApiConstants.PASSWORD, password); | |||
Disposable disposableLogin = clientApi.login(data) | |||
.subscribeOn(Schedulers.newThread()) | |||
.observeOn(AndroidSchedulers.mainThread()) | |||
.subscribe(user -> { | |||
UserStore.getInstance(context).setToken(user.getToken()); | |||
if (!isDeviceLoggedIn(context)) { | |||
addDevice(context); | |||
} | |||
else { | |||
String errorMessage = createErrorMessage(call,response); | |||
setMutableLiveData(StatusResource.error(errorMessage)); | |||
getAllDevices(context); | |||
} | |||
}, throwable -> { | |||
setMutableLiveData(StatusResource.error(throwable.getMessage())); | |||
}); | |||
compositeDisposable.add(disposableLogin); | |||
} | |||
@Override public void onFailure(final Call<User> call, final Throwable t) { | |||
if(t instanceof Exception){ | |||
setMutableLiveData(StatusResource.error(NO_INTERNET_CONNECTION)); | |||
private void getAllDevices(final Context context) { | |||
final String token = UserStore.getInstance(context).getToken(); | |||
final HashMap<String,String> header = new HashMap<>(); | |||
header.put(ApiConstants.AUTHORIZATION_HEADER,token); | |||
Disposable disposableAllDevices = clientApi.getAllDevices(header) | |||
.subscribeOn(Schedulers.newThread()) | |||
.observeOn(AndroidSchedulers.mainThread()) | |||
.subscribe(listDevices->{ | |||
boolean hasDevice = false; | |||
for (Device item : listDevices) { | |||
if (UserStore.getInstance(context).getDeviceID().equals(item.getUuid())) { | |||
setMutableLiveData(StatusResource.success()); | |||
hasDevice = true; | |||
break; | |||
} | |||
} | |||
if(!hasDevice) { | |||
addDevice(context); | |||
} | |||
},throwable -> { | |||
}); | |||
compositeDisposable.add(disposableAllDevices); | |||
} | |||
private void addDevice(final Context context) { | |||
final String brand = getBrand(); | |||
final String model = getDeviceModel(); | |||
final String imei = getDeviceID(context); | |||
final String deviceName = brand + SPACE + model + SPACE + SEPARATOR + SPACE + imei; | |||
final String token = UserStore.getInstance(context).getToken(); | |||
final HashMap<String, String> header = new HashMap<>(); | |||
header.put(ApiConstants.AUTHORIZATION_HEADER, token); | |||
final Disposable disposableAllDevices = clientApi.getAllDevices(header) | |||
.subscribeOn(Schedulers.newThread()) | |||
.observeOn(AndroidSchedulers.mainThread()) | |||
.subscribe(listDevices -> { | |||
String brandModel = brand + SPACE + model + SPACE; | |||
final List<Device> list = listDevices; | |||
final List<String> arrayListDevicesName = new ArrayList<>(); | |||
boolean hasDevice = false; | |||
for (final Device device : list) { | |||
final String[] deviceNameItem = device.getName().split(SEPARATOR); | |||
final String[] myDeviceName = deviceName.split(SEPARATOR); | |||
if (deviceNameItem.length > 1) { | |||
if (deviceNameItem[ANDROID_ID].equals(myDeviceName[ANDROID_ID])) { | |||
UserStore.getInstance(context).setDeviceName(device.getName()); | |||
UserStore.getInstance(context).setDeviceID(device.getUuid()); | |||
hasDevice = true; | |||
setMutableLiveData(StatusResource.success()); | |||
break; | |||
} else { | |||
final String[] itemDevice = device.getName().split(SEPARATOR); | |||
if (itemDevice.length != 1) { | |||
gegham commented 4 years ago
Review
Put all the hardcoded strings in constants: " “, " : " Put all the hardcoded strings in constants: " ", " : "
|
|||
if (itemDevice[0].contains(brandModel)) { | |||
arrayListDevicesName.add(itemDevice[0]); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
if (!hasDevice) { | |||
if (arrayListDevicesName.isEmpty()) { | |||
gegham commented 4 years ago
Review
Rename the boolean Rename the boolean
|
|||
brandModel = deviceName; | |||
final HashMap<String, String> body = new HashMap<>(); | |||
body.put(ApiConstants.DEVICE_NAME, brandModel); | |||
body.put(ApiConstants.DEVICE_TYPE, "android"); | |||
gegham commented 4 years ago
Review
Rename disposable2 and disposable properties accordingly Rename disposable2 and disposable properties accordingly
|
|||
final Disposable disposableAddDevice = clientApi.addDevice(header, body) | |||
gegham commented 4 years ago
Review
Change magic numbers to constants Change magic numbers to constants
|
|||
.subscribeOn(Schedulers.newThread()) | |||
.observeOn(AndroidSchedulers.mainThread()) | |||
.subscribe(device -> { | |||
UserStore.getInstance(context).setDeviceName(device.getName()); | |||
UserStore.getInstance(context).setDeviceID(device.getUuid()); | |||
setMutableLiveData(StatusResource.success()); | |||
}, throwable -> { | |||
setMutableLiveData(StatusResource.error(throwable.getMessage())); | |||
}); | |||
compositeDisposable.add(disposableAddDevice); | |||
} | |||
else { | |||
for (int i = (arrayListDevicesName.size() - 1); i >= arrayListDevicesName.size() - 1; i--) { | |||
if (arrayListDevicesName.get(i).contains(brandModel)) { | |||
final char[] arr = arrayListDevicesName.get(i).toCharArray(); | |||
if (arr[arr.length - 2] != ')') { | |||
brandModel += "(2)" + SPACE + SEPARATOR + SPACE + imei; | |||
} else { | |||
String countDevice = ""; | |||
int indexfirst = 0; | |||
int indexlast = 0; | |||
for (int j = arr.length - 1; j >= 0; j--) { | |||
if (arr[j] == '(') { | |||
indexfirst = j; | |||
} | |||
if (arr[j] == ')') { | |||
indexlast = j; | |||
} | |||
} | |||
final String device = new String(arr); | |||
countDevice += device.substring(indexfirst + 1, indexlast); | |||
int count = Integer.parseInt(countDevice); | |||
count++; | |||
brandModel += "(" + count + ")" + SPACE + SEPARATOR + SPACE + imei; | |||
} | |||
} | |||
final HashMap<String, String> body = new HashMap<>(); | |||
body.put(ApiConstants.DEVICE_NAME, brandModel); | |||
body.put(ApiConstants.DEVICE_TYPE, "android"); | |||
Disposable disposableAddDevice = clientApi.addDevice(header,body) | |||
.subscribeOn(Schedulers.newThread()) | |||
.observeOn(AndroidSchedulers.mainThread()) | |||
.subscribe(device -> { | |||
UserStore.getInstance(context).setDeviceName(device.getName()); | |||
UserStore.getInstance(context).setDeviceID(device.getUuid()); | |||
setMutableLiveData(StatusResource.success()); | |||
},throwable -> { | |||
setMutableLiveData(StatusResource.error(throwable.getMessage())); | |||
}); | |||
compositeDisposable.add(disposableAddDevice); | |||
} | |||
} | |||
} | |||
}, throwable -> { | |||
setMutableLiveData(StatusResource.error(NO_INTERNET_CONNECTION)); | |||
}); | |||
compositeDisposable.add(disposableAllDevices); | |||
} | |||
}.getMutableLiveData(); | |||
} | |||
private boolean isDeviceLoggedIn(Context context) { | |||
return !UserStore.DEVICE_DEFAULT_VALUE.equals(UserStore.getInstance(context).getDeviceName()); | |||
} | |||
private String createErrorMessage(Call call, retrofit2.Response response) { | |||
return "Error: User agent: " + System.getProperty("http.agent") + ", Request body: " + call.request().body() + ", URL: " + | |||
@@ -78,9 +215,33 @@ public class DataRepository { | |||
response.message(); | |||
} | |||
public boolean isUserLoggedIn(Context context) | |||
{ | |||
public boolean isUserLoggedIn(Context context) { | |||
return !UserStore.USER_TOKEN_DEFAULT_VALUE.equals(UserStore.getInstance(context).getToken()); | |||
} | |||
private String getBrand() { | |||
final String brand = Build.MANUFACTURER; | |||
return capitalize(brand); | |||
} | |||
private String capitalize(final String brand) { | |||
if (brand == null || brand.isEmpty()) { | |||
return ""; | |||
} | |||
final char first = brand.charAt(0); | |||
return Character.isUpperCase(first) ? brand : Character.toUpperCase(first) + brand.substring(1); | |||
} | |||
private String getDeviceID(final Context context) { | |||
return Settings.Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); | |||
} | |||
private String getDeviceModel() { | |||
return Build.MODEL; | |||
} | |||
public void clearDisposable(){ | |||
compositeDisposable.clear(); | |||
} | |||
} |
@@ -9,7 +9,11 @@ public class UserStore { | |||
private static final String USER_SHARED_PREF = "com.wireguard.android.util.bubbleUserSharedPref"; | |||
private static final String USER_DATA_KEY = "com.wireguard.android.util.bubbleUserResponse"; | |||
private static final String DEVICE_DATA_KEY = "com.wireguard.android.util.bubbleDeviceResponse"; | |||
private static final String DEVICE_ID_KEY = "com.wireguard.android.util.bubbleDeviceIDResponse"; | |||
public static final String USER_TOKEN_DEFAULT_VALUE = ""; | |||
public static final String DEVICE_DEFAULT_VALUE = ""; | |||
public static final String DEVICE_ID_DEFAULT_VALUE = ""; | |||
public static UserStore getInstance(Context context) { | |||
if (instance == null) { | |||
@@ -35,4 +39,19 @@ public class UserStore { | |||
return sharedPreferences.getString(USER_DATA_KEY, USER_TOKEN_DEFAULT_VALUE); | |||
} | |||
public void setDeviceName(String device){ | |||
sharedPreferences.edit().putString(DEVICE_DATA_KEY, device).apply(); | |||
} | |||
public String getDeviceName(){ | |||
return sharedPreferences.getString(DEVICE_DATA_KEY, DEVICE_DEFAULT_VALUE); | |||
} | |||
public void setDeviceID(String id){ | |||
sharedPreferences.edit().putString(DEVICE_ID_KEY,id).apply(); | |||
} | |||
public String getDeviceID(){ | |||
return sharedPreferences.getString(DEVICE_ID_KEY,DEVICE_ID_DEFAULT_VALUE); | |||
} | |||
} |
@@ -1,13 +1,9 @@ | |||
package com.wireguard.android.viewmodel; | |||
import android.content.Context; | |||
import com.wireguard.android.model.User; | |||
import com.wireguard.android.repository.DataRepository; | |||
import com.wireguard.android.resource.StatusResource; | |||
import java.util.HashMap; | |||
import androidx.lifecycle.LiveData; | |||
import androidx.lifecycle.ViewModel; | |||
@@ -15,4 +11,9 @@ public class LoginViewModel extends ViewModel { | |||
public LiveData<StatusResource<User>> login(String username,String password, Context context){ | |||
return DataRepository.getRepositoryInstance().login(username,password,context); | |||
} | |||
@Override protected void onCleared() { | |||
super.onCleared(); | |||
DataRepository.getRepositoryInstance().clearDisposable(); | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:orientation="vertical" | |||
android:gravity="center_vertical" | |||
android:background="@android:color/transparent"> | |||
<ProgressBar | |||
android:id="@+id/progress" | |||
android:layout_width="40dp" | |||
android:layout_height="40dp" | |||
android:layout_gravity="center_horizontal" | |||
/> | |||
<TextView | |||
android:id="@+id/loading_TextView" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:text="@string/progress_bar_text" | |||
android:layout_gravity="center" | |||
android:textColor="@android:color/white" | |||
android:textSize="17sp"/> | |||
</LinearLayout> |
@@ -25,4 +25,6 @@ | |||
<color name="error_tag_color">#aa0000</color> | |||
<color name="info_tag_color">#00aa00</color> | |||
<color name="warning_tag_color">#aaaa00</color> | |||
<color name="colorPrimaryDark">#C04B26</color> | |||
</resources> |
@@ -241,4 +241,5 @@ | |||
<string name="connect">Connect</string> | |||
<string name="disable_apps">Disable Apps</string> | |||
<string name="turnInternet">Please turn on internet connection</string> | |||
<string name="progress_bar_text">Loading</string> | |||
</resources> |
Do we need to have the BaseActivity in Manifest?