Reviewed-on: https://git.bubblev.org/bubblev/bubble-droid/pulls/4pull/5/head
@@ -38,6 +38,9 @@ buildscript { | |||||
constraintlayoutVersion = '1.1.3' | constraintlayoutVersion = '1.1.3' | ||||
lifecycleExtensionVersion = '2.2.0' | lifecycleExtensionVersion = '2.2.0' | ||||
lifecycleViewModelVersion = '2.2.0' | lifecycleViewModelVersion = '2.2.0' | ||||
rxandroidVersion = '2.0.1' | |||||
rxjavaVersion = '2.1.6' | |||||
adapterrxjava2Version = '2.3.0' | |||||
groupName = 'com.wireguard.android' | groupName = 'com.wireguard.android' | ||||
} | } | ||||
@@ -90,6 +90,10 @@ dependencies { | |||||
implementation "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion" | implementation "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion" | ||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionVersion" | implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionVersion" | ||||
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycleViewModelVersion" | 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) { | tasks.withType(JavaCompile) { | ||||
@@ -72,7 +72,6 @@ | |||||
<action android:name="android.intent.action.MAIN" /> | <action android:name="android.intent.action.MAIN" /> | ||||
</intent-filter> | </intent-filter> | ||||
</activity> | </activity> | ||||
<provider | <provider | ||||
android:name=".activity.LogViewerActivity$ExportedLogContentProvider" | android:name=".activity.LogViewerActivity$ExportedLogContentProvider" | ||||
android:authorities="${applicationId}.exported-log" | 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; | package com.wireguard.android.activity; | ||||
import androidx.appcompat.app.AppCompatActivity; | |||||
import androidx.lifecycle.Observer; | import androidx.lifecycle.Observer; | ||||
import androidx.lifecycle.ViewModelProvider; | import androidx.lifecycle.ViewModelProvider; | ||||
import android.os.Bundle; | import android.os.Bundle; | ||||
@@ -12,14 +10,11 @@ import android.widget.Button; | |||||
import android.widget.EditText; | import android.widget.EditText; | ||||
import android.widget.Toast; | import android.widget.Toast; | ||||
import com.wireguard.android.R; | import com.wireguard.android.R; | ||||
import com.wireguard.android.api.ApiConstants; | |||||
import com.wireguard.android.model.User; | import com.wireguard.android.model.User; | ||||
import com.wireguard.android.resource.StatusResource; | import com.wireguard.android.resource.StatusResource; | ||||
import com.wireguard.android.viewmodel.LoginViewModel; | import com.wireguard.android.viewmodel.LoginViewModel; | ||||
import java.util.HashMap; | |||||
public class LoginActivity extends AppCompatActivity { | |||||
public class LoginActivity extends BaseActivityBubble { | |||||
private LoginViewModel loginViewModel; | private LoginViewModel loginViewModel; | ||||
private EditText bubbleName; | private EditText bubbleName; | ||||
@@ -45,6 +40,7 @@ public class LoginActivity extends AppCompatActivity { | |||||
@Override public void onClick(final View v) { | @Override public void onClick(final View v) { | ||||
final String username = userName.getText().toString().trim(); | final String username = userName.getText().toString().trim(); | ||||
final String password = LoginActivity.this.password.getText().toString().trim(); | final String password = LoginActivity.this.password.getText().toString().trim(); | ||||
showLoadingDialog(); | |||||
login(username,password); | login(username,password); | ||||
} | } | ||||
}); | }); | ||||
@@ -60,18 +56,20 @@ public class LoginActivity extends AppCompatActivity { | |||||
private void login(String username, String password) { | private void login(String username, String password) { | ||||
loginViewModel.login(username,password,this).observe(this, new Observer<StatusResource<User>>() { | loginViewModel.login(username,password,this).observe(this, new Observer<StatusResource<User>>() { | ||||
@Override public void onChanged(final StatusResource<User> userStatusResource) { | @Override public void onChanged(final StatusResource<User> userStatusResource) { | ||||
switch (userStatusResource.status){ | |||||
switch (userStatusResource.status) { | |||||
case SUCCESS: | case SUCCESS: | ||||
Toast.makeText(LoginActivity.this,"Success",Toast.LENGTH_SHORT).show(); | |||||
Log.d("TAG","Success"); | |||||
break; | |||||
case LOADING: | |||||
Log.d("TAG","Loading"); | |||||
break; | |||||
case ERROR: | |||||
Toast.makeText(LoginActivity.this,"Login Failed",Toast.LENGTH_SHORT).show(); | |||||
Log.d("TAG","Error"); | |||||
break; | |||||
Toast.makeText(LoginActivity.this, "Success", Toast.LENGTH_SHORT).show(); | |||||
Log.d("TAG", "Success"); | |||||
closeLoadingDialog(); | |||||
break; | |||||
case LOADING: | |||||
Log.d("TAG", "Loading"); | |||||
break; | |||||
case 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 class ApiConstants { | ||||
public static final String BASE_URL = "https://jtest2.bubblesecure.com:1443/api/"; | public static final String BASE_URL = "https://jtest2.bubblesecure.com:1443/api/"; | ||||
public static final String LOGIN_URL = "auth/login"; | 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 USERNAME = "username"; | ||||
public static final String PASSWORD = "password"; | 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; | package com.wireguard.android.api.network; | ||||
import com.wireguard.android.api.ApiConstants; | import com.wireguard.android.api.ApiConstants; | ||||
import com.wireguard.android.model.Device; | |||||
import com.wireguard.android.model.User; | import com.wireguard.android.model.User; | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.List; | |||||
import io.reactivex.Single; | |||||
import retrofit2.Call; | import retrofit2.Call; | ||||
import retrofit2.http.Body; | import retrofit2.http.Body; | ||||
import retrofit2.http.GET; | |||||
import retrofit2.http.HeaderMap; | |||||
import retrofit2.http.POST; | import retrofit2.http.POST; | ||||
import retrofit2.http.PUT; | |||||
/** | /** | ||||
Interface for API Calls | Interface for API Calls | ||||
@@ -15,5 +22,11 @@ import retrofit2.http.POST; | |||||
public interface ClientApi { | public interface ClientApi { | ||||
@POST(ApiConstants.LOGIN_URL) | @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.OkHttpClient; | ||||
import okhttp3.logging.HttpLoggingInterceptor; | import okhttp3.logging.HttpLoggingInterceptor; | ||||
import retrofit2.Retrofit; | import retrofit2.Retrofit; | ||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; | |||||
import retrofit2.converter.gson.GsonConverterFactory; | import retrofit2.converter.gson.GsonConverterFactory; | ||||
public class ClientService { | public class ClientService { | ||||
@@ -41,6 +42,7 @@ public class ClientService { | |||||
return new Retrofit.Builder() | return new Retrofit.Builder() | ||||
.baseUrl(ApiConstants.BASE_URL) | .baseUrl(ApiConstants.BASE_URL) | ||||
.addConverterFactory(GsonConverterFactory.create()) | .addConverterFactory(GsonConverterFactory.create()) | ||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) | |||||
.client(httpClient.build()) | .client(httpClient.build()) | ||||
.build().create(ClientApi.class); | .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() { | |||||
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; | package com.wireguard.android.repository; | ||||
import android.content.Context; | 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.ApiConstants; | ||||
import com.wireguard.android.api.network.ClientApi; | import com.wireguard.android.api.network.ClientApi; | ||||
import com.wireguard.android.api.network.ClientService; | import com.wireguard.android.api.network.ClientService; | ||||
import com.wireguard.android.api.network.NetworkBoundStatusResource; | import com.wireguard.android.api.network.NetworkBoundStatusResource; | ||||
import com.wireguard.android.model.Device; | |||||
import com.wireguard.android.model.User; | import com.wireguard.android.model.User; | ||||
import com.wireguard.android.resource.StatusResource; | import com.wireguard.android.resource.StatusResource; | ||||
import com.wireguard.android.util.UserStore; | import com.wireguard.android.util.UserStore; | ||||
import java.util.ArrayList; | |||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.List; | |||||
import androidx.lifecycle.MutableLiveData; | 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.Call; | ||||
import retrofit2.Callback; | |||||
import retrofit2.Response; | |||||
public class DataRepository { | public class DataRepository { | ||||
private static volatile DataRepository instance; | private static volatile DataRepository instance; | ||||
private ClientApi clientApi; | private ClientApi clientApi; | ||||
private CompositeDisposable compositeDisposable; | |||||
public static final String NO_INTERNET_CONNECTION = "no_internet_connection"; | 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(); | clientApi = ClientService.getInstance().createClientApi(); | ||||
compositeDisposable = new CompositeDisposable(); | |||||
} | } | ||||
public static void buildRepositoryInstance() { | public static void buildRepositoryInstance() { | ||||
@@ -41,36 +51,163 @@ public class DataRepository { | |||||
return instance; | 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() { | @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()); | |||||
} | |||||
else { | |||||
String errorMessage = createErrorMessage(call,response); | |||||
setMutableLiveData(StatusResource.error(errorMessage)); | |||||
} | |||||
} | |||||
@Override public void onFailure(final Call<User> call, final Throwable t) { | |||||
if(t instanceof Exception){ | |||||
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 { | |||||
getAllDevices(context); | |||||
} | |||||
}, throwable -> { | |||||
setMutableLiveData(StatusResource.error(throwable.getMessage())); | |||||
}); | |||||
compositeDisposable.add(disposableLogin); | |||||
} | |||||
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) { | |||||
if (itemDevice[0].contains(brandModel)) { | |||||
arrayListDevicesName.add(itemDevice[0]); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if (!hasDevice) { | |||||
if (arrayListDevicesName.isEmpty()) { | |||||
brandModel = deviceName; | |||||
final HashMap<String, String> body = new HashMap<>(); | |||||
body.put(ApiConstants.DEVICE_NAME, brandModel); | |||||
body.put(ApiConstants.DEVICE_TYPE, "android"); | |||||
final 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); | |||||
} | |||||
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)); | setMutableLiveData(StatusResource.error(NO_INTERNET_CONNECTION)); | ||||
} | |||||
} | |||||
}); | |||||
}); | |||||
compositeDisposable.add(disposableAllDevices); | |||||
} | } | ||||
}.getMutableLiveData(); | }.getMutableLiveData(); | ||||
} | } | ||||
private boolean isDeviceLoggedIn(Context context) { | |||||
return !UserStore.DEVICE_DEFAULT_VALUE.equals(UserStore.getInstance(context).getDeviceName()); | |||||
} | |||||
private String createErrorMessage(Call call, retrofit2.Response response) { | private String createErrorMessage(Call call, retrofit2.Response response) { | ||||
return "Error: User agent: " + System.getProperty("http.agent") + ", Request body: " + call.request().body() + ", URL: " + | return "Error: User agent: " + System.getProperty("http.agent") + ", Request body: " + call.request().body() + ", URL: " + | ||||
@@ -78,9 +215,33 @@ public class DataRepository { | |||||
response.message(); | response.message(); | ||||
} | } | ||||
public boolean isUserLoggedIn(Context context) | |||||
{ | |||||
public boolean isUserLoggedIn(Context context) { | |||||
return !UserStore.USER_TOKEN_DEFAULT_VALUE.equals(UserStore.getInstance(context).getToken()); | 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_SHARED_PREF = "com.wireguard.android.util.bubbleUserSharedPref"; | ||||
private static final String USER_DATA_KEY = "com.wireguard.android.util.bubbleUserResponse"; | 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 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) { | public static UserStore getInstance(Context context) { | ||||
if (instance == null) { | if (instance == null) { | ||||
@@ -35,4 +39,19 @@ public class UserStore { | |||||
return sharedPreferences.getString(USER_DATA_KEY, USER_TOKEN_DEFAULT_VALUE); | 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; | package com.wireguard.android.viewmodel; | ||||
import android.content.Context; | import android.content.Context; | ||||
import com.wireguard.android.model.User; | import com.wireguard.android.model.User; | ||||
import com.wireguard.android.repository.DataRepository; | import com.wireguard.android.repository.DataRepository; | ||||
import com.wireguard.android.resource.StatusResource; | import com.wireguard.android.resource.StatusResource; | ||||
import java.util.HashMap; | |||||
import androidx.lifecycle.LiveData; | import androidx.lifecycle.LiveData; | ||||
import androidx.lifecycle.ViewModel; | import androidx.lifecycle.ViewModel; | ||||
@@ -15,4 +11,9 @@ public class LoginViewModel extends ViewModel { | |||||
public LiveData<StatusResource<User>> login(String username,String password, Context context){ | public LiveData<StatusResource<User>> login(String username,String password, Context context){ | ||||
return DataRepository.getRepositoryInstance().login(username,password,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="error_tag_color">#aa0000</color> | ||||
<color name="info_tag_color">#00aa00</color> | <color name="info_tag_color">#00aa00</color> | ||||
<color name="warning_tag_color">#aaaa00</color> | <color name="warning_tag_color">#aaaa00</color> | ||||
<color name="colorPrimaryDark">#C04B26</color> | |||||
</resources> | </resources> |
@@ -241,4 +241,5 @@ | |||||
<string name="connect">Connect</string> | <string name="connect">Connect</string> | ||||
<string name="disable_apps">Disable Apps</string> | <string name="disable_apps">Disable Apps</string> | ||||
<string name="turnInternet">Please turn on internet connection</string> | <string name="turnInternet">Please turn on internet connection</string> | ||||
<string name="progress_bar_text">Loading</string> | |||||
</resources> | </resources> |