mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-08-04 03:06:41 -04:00
Merge pull request #1506 from kiwix/iadeelzafar/manual-hotspot
Iadeelzafar/manual hotspot
This commit is contained in:
commit
f9e722f72f
@ -12,9 +12,6 @@
|
|||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
|
||||||
<!-- Devices with version >= Oreo need location permission to start/stop the hotspot -->
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
||||||
|
|
||||||
<!-- Device with versions >= Pie need this permission -->
|
<!-- Device with versions >= Pie need this permission -->
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package org.kiwix.kiwixmobile.di.modules
|
package org.kiwix.kiwixmobile.di.modules
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.wifi.WifiManager
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import org.kiwix.kiwixlib.JNIKiwixLibrary
|
import org.kiwix.kiwixlib.JNIKiwixLibrary
|
||||||
@ -12,9 +10,9 @@ import org.kiwix.kiwixlib.JNIKiwixServer
|
|||||||
import org.kiwix.kiwixmobile.di.ServiceScope
|
import org.kiwix.kiwixmobile.di.ServiceScope
|
||||||
import org.kiwix.kiwixmobile.webserver.WebServerHelper
|
import org.kiwix.kiwixmobile.webserver.WebServerHelper
|
||||||
import org.kiwix.kiwixmobile.wifi_hotspot.HotspotNotificationManager
|
import org.kiwix.kiwixmobile.wifi_hotspot.HotspotNotificationManager
|
||||||
import org.kiwix.kiwixmobile.wifi_hotspot.HotspotStateListener
|
import org.kiwix.kiwixmobile.wifi_hotspot.HotspotStateReceiver
|
||||||
|
import org.kiwix.kiwixmobile.wifi_hotspot.HotspotStateReceiver.Callback
|
||||||
import org.kiwix.kiwixmobile.wifi_hotspot.IpAddressCallbacks
|
import org.kiwix.kiwixmobile.wifi_hotspot.IpAddressCallbacks
|
||||||
import org.kiwix.kiwixmobile.wifi_hotspot.WifiHotspotManager
|
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
class ServiceModule {
|
class ServiceModule {
|
||||||
@ -27,19 +25,6 @@ class ServiceModule {
|
|||||||
ipAddressCallbacks: IpAddressCallbacks
|
ipAddressCallbacks: IpAddressCallbacks
|
||||||
): WebServerHelper = WebServerHelper(jniKiwixLibrary, kiwixServer, ipAddressCallbacks)
|
): WebServerHelper = WebServerHelper(jniKiwixLibrary, kiwixServer, ipAddressCallbacks)
|
||||||
|
|
||||||
@Provides
|
|
||||||
@ServiceScope
|
|
||||||
fun providesWifiHotspotManager(
|
|
||||||
wifiManager: WifiManager,
|
|
||||||
hotspotStateListener: HotspotStateListener
|
|
||||||
): WifiHotspotManager =
|
|
||||||
WifiHotspotManager(wifiManager, hotspotStateListener)
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@ServiceScope
|
|
||||||
fun providesHotspotStateListener(service: Service): HotspotStateListener =
|
|
||||||
service as HotspotStateListener
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@ServiceScope
|
@ServiceScope
|
||||||
fun providesIpAddressCallbacks(service: Service): IpAddressCallbacks =
|
fun providesIpAddressCallbacks(service: Service): IpAddressCallbacks =
|
||||||
@ -54,11 +39,6 @@ class ServiceModule {
|
|||||||
fun providesJNIKiwixServer(jniKiwixLibrary: JNIKiwixLibrary): JNIKiwixServer =
|
fun providesJNIKiwixServer(jniKiwixLibrary: JNIKiwixLibrary): JNIKiwixServer =
|
||||||
JNIKiwixServer(jniKiwixLibrary)
|
JNIKiwixServer(jniKiwixLibrary)
|
||||||
|
|
||||||
@Provides
|
|
||||||
@ServiceScope
|
|
||||||
fun providesWifiManager(context: Application): WifiManager =
|
|
||||||
context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@ServiceScope
|
@ServiceScope
|
||||||
fun providesHotspotNotificationManager(
|
fun providesHotspotNotificationManager(
|
||||||
@ -66,4 +46,16 @@ class ServiceModule {
|
|||||||
context: Context
|
context: Context
|
||||||
): HotspotNotificationManager =
|
): HotspotNotificationManager =
|
||||||
HotspotNotificationManager(notificationManager, context)
|
HotspotNotificationManager(notificationManager, context)
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@ServiceScope
|
||||||
|
fun providesHotspotStateReceiver(
|
||||||
|
callback: Callback
|
||||||
|
): HotspotStateReceiver = HotspotStateReceiver(callback)
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@ServiceScope
|
||||||
|
fun providesHotspotStateReceiverCallback(
|
||||||
|
service: Service
|
||||||
|
): HotspotStateReceiver.Callback = service as Callback
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package org.kiwix.kiwixmobile.webserver;
|
|
||||||
|
|
||||||
public interface LocationCallbacks {
|
|
||||||
void onLocationSet();
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
package org.kiwix.kiwixmobile.webserver;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentSender;
|
|
||||||
import android.util.Log;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import com.google.android.gms.common.api.ApiException;
|
|
||||||
import com.google.android.gms.common.api.ResolvableApiException;
|
|
||||||
import com.google.android.gms.location.LocationRequest;
|
|
||||||
import com.google.android.gms.location.LocationSettingsRequest;
|
|
||||||
import com.google.android.gms.location.LocationSettingsResponse;
|
|
||||||
import com.google.android.gms.location.LocationSettingsStates;
|
|
||||||
import com.google.android.gms.location.LocationSettingsStatusCodes;
|
|
||||||
import com.google.android.gms.tasks.Task;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public class LocationServicesHelper {
|
|
||||||
private static final String TAG = "LocationServicesHelper";
|
|
||||||
private final LocationCallbacks locationCallbacks;
|
|
||||||
private final Activity activity;
|
|
||||||
private static final int LOCATION_SETTINGS_PERMISSION_RESULT = 101;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public LocationServicesHelper(@NonNull Activity activity,
|
|
||||||
@NonNull LocationCallbacks locationCallbacks) {
|
|
||||||
this.activity = activity;
|
|
||||||
this.locationCallbacks = locationCallbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task<LocationSettingsResponse> task;
|
|
||||||
|
|
||||||
public void setupLocationServices() {
|
|
||||||
LocationRequest locationRequest = new LocationRequest();
|
|
||||||
locationRequest.setInterval(10);
|
|
||||||
locationRequest.setSmallestDisplacement(10);
|
|
||||||
locationRequest.setFastestInterval(10);
|
|
||||||
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
|
|
||||||
LocationSettingsRequest.Builder builder = new
|
|
||||||
LocationSettingsRequest.Builder();
|
|
||||||
builder.addLocationRequest(locationRequest);
|
|
||||||
|
|
||||||
task = com.google.android.gms.location.LocationServices.getSettingsClient(activity)
|
|
||||||
.checkLocationSettings(builder.build());
|
|
||||||
|
|
||||||
locationSettingsResponseBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void locationSettingsResponseBuilder() {
|
|
||||||
task.addOnCompleteListener(task -> {
|
|
||||||
try {
|
|
||||||
LocationSettingsResponse response = task.getResult(ApiException.class);
|
|
||||||
// All location settings are satisfied. The client can initialize location
|
|
||||||
// requests here.
|
|
||||||
|
|
||||||
locationCallbacks.onLocationSet();
|
|
||||||
//}
|
|
||||||
} catch (ApiException exception) {
|
|
||||||
switch (exception.getStatusCode()) {
|
|
||||||
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
|
|
||||||
// Location settings are not satisfied. But could be fixed by showing the
|
|
||||||
// user a dialog.
|
|
||||||
try {
|
|
||||||
// Cast to a resolvable exception.
|
|
||||||
ResolvableApiException resolvable = (ResolvableApiException) exception;
|
|
||||||
// Show the dialog by calling startResolutionForResult(),
|
|
||||||
// and check the result in onActivityResult().
|
|
||||||
resolvable.startResolutionForResult(
|
|
||||||
activity,
|
|
||||||
LOCATION_SETTINGS_PERMISSION_RESULT);
|
|
||||||
} catch (IntentSender.SendIntentException e) {
|
|
||||||
// Ignore the error.
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
// Ignore, should be an impossible error.
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
|
|
||||||
// Location settings are not satisfied. However, we have no way to fix the
|
|
||||||
// settings so we won't show the dialog.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onActivityResult(int requestCode, int resultCode, @NonNull Intent data) {
|
|
||||||
//Checking the result code for LocationSettings resolution
|
|
||||||
if (requestCode == LOCATION_SETTINGS_PERMISSION_RESULT) {
|
|
||||||
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
|
|
||||||
switch (resultCode) {
|
|
||||||
case Activity.RESULT_OK:
|
|
||||||
// All required changes were successfully made
|
|
||||||
Log.v(TAG, states.isLocationPresent() + "");
|
|
||||||
locationCallbacks.onLocationSet();
|
|
||||||
break;
|
|
||||||
case Activity.RESULT_CANCELED:
|
|
||||||
// The user was asked to change settings, but chose not to
|
|
||||||
Log.v(TAG, "Canceled");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,10 @@
|
|||||||
package org.kiwix.kiwixmobile.webserver;
|
package org.kiwix.kiwixmobile.webserver;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.wifi.WifiConfiguration;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -18,8 +14,6 @@ import android.widget.Toast;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -40,13 +34,11 @@ import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskAdap
|
|||||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem;
|
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem;
|
||||||
|
|
||||||
import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotService.ACTION_CHECK_IP_ADDRESS;
|
import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotService.ACTION_CHECK_IP_ADDRESS;
|
||||||
import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotService.ACTION_LOCATION_ACCESS_GRANTED;
|
|
||||||
import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotService.ACTION_START_SERVER;
|
import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotService.ACTION_START_SERVER;
|
||||||
import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotService.ACTION_STOP_SERVER;
|
import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotService.ACTION_STOP_SERVER;
|
||||||
import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotService.ACTION_TOGGLE_HOTSPOT;
|
|
||||||
|
|
||||||
public class ZimHostActivity extends BaseActivity implements
|
public class ZimHostActivity extends BaseActivity implements
|
||||||
ZimHostCallbacks, ZimHostContract.View, LocationCallbacks {
|
ZimHostCallbacks, ZimHostContract.View {
|
||||||
|
|
||||||
@BindView(R.id.startServerButton)
|
@BindView(R.id.startServerButton)
|
||||||
Button startServerButton;
|
Button startServerButton;
|
||||||
@ -61,11 +53,7 @@ public class ZimHostActivity extends BaseActivity implements
|
|||||||
@Inject
|
@Inject
|
||||||
AlertDialogShower alertDialogShower;
|
AlertDialogShower alertDialogShower;
|
||||||
|
|
||||||
@Inject
|
|
||||||
LocationServicesHelper locationServicesHelper;
|
|
||||||
|
|
||||||
private static final String TAG = "ZimHostActivity";
|
private static final String TAG = "ZimHostActivity";
|
||||||
private static final int MY_PERMISSIONS_ACCESS_FINE_LOCATION = 102;
|
|
||||||
private static final String IP_STATE_KEY = "ip_state_key";
|
private static final String IP_STATE_KEY = "ip_state_key";
|
||||||
public static final String SELECTED_ZIM_PATHS_KEY = "selected_zim_paths";
|
public static final String SELECTED_ZIM_PATHS_KEY = "selected_zim_paths";
|
||||||
|
|
||||||
@ -133,16 +121,12 @@ public class ZimHostActivity extends BaseActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startHotspotHelper() {
|
private void startHotspotHelper() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
toggleHotspot();
|
|
||||||
} else {
|
|
||||||
if (ServerUtils.isServerStarted) {
|
if (ServerUtils.isServerStarted) {
|
||||||
startService(createHotspotIntent(ACTION_STOP_SERVER));
|
startService(createHotspotIntent(ACTION_STOP_SERVER));
|
||||||
} else {
|
} else {
|
||||||
startHotspotManuallyDialog();
|
startHotspotManuallyDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private ArrayList<String> getSelectedBooksPath() {
|
private ArrayList<String> getSelectedBooksPath() {
|
||||||
ArrayList<String> selectedBooksPath = new ArrayList<>();
|
ArrayList<String> selectedBooksPath = new ArrayList<>();
|
||||||
@ -190,21 +174,6 @@ public class ZimHostActivity extends BaseActivity implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toggleHotspot() {
|
|
||||||
//Check if location permissions are granted
|
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
|
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
|
||||||
//Toggle hotspot if location permissions are granted
|
|
||||||
startService(createHotspotIntent(
|
|
||||||
ACTION_TOGGLE_HOTSPOT));
|
|
||||||
} else {
|
|
||||||
//Ask location permission if not granted
|
|
||||||
ActivityCompat.requestPermissions(this,
|
|
||||||
new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
|
|
||||||
MY_PERMISSIONS_ACCESS_FINE_LOCATION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected void onResume() {
|
@Override protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
presenter.loadBooks();
|
presenter.loadBooks();
|
||||||
@ -233,23 +202,6 @@ public class ZimHostActivity extends BaseActivity implements
|
|||||||
booksAdapter.notifyDataSetChanged();
|
booksAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
|
||||||
@NonNull int[] grantResults) {
|
|
||||||
if (requestCode == MY_PERMISSIONS_ACCESS_FINE_LOCATION) {
|
|
||||||
if (grantResults.length > 0
|
|
||||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
toggleHotspot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
|
||||||
locationServicesHelper.onActivityResult(requestCode, resultCode, (data));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected void onDestroy() {
|
@Override protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
presenter.detachView();
|
presenter.detachView();
|
||||||
@ -302,18 +254,6 @@ public class ZimHostActivity extends BaseActivity implements
|
|||||||
Toast.makeText(this, R.string.server_failed_toast_message, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.server_failed_toast_message, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onHotspotTurnedOn(@NonNull WifiConfiguration wifiConfiguration) {
|
|
||||||
alertDialogShower.show(new KiwixDialog.ShowHotspotDetails(wifiConfiguration),
|
|
||||||
(Function0<Unit>) () -> {
|
|
||||||
progressDialog =
|
|
||||||
ProgressDialog.show(this,
|
|
||||||
getString(R.string.progress_dialog_starting_server), "",
|
|
||||||
true);
|
|
||||||
startService(createHotspotIntent(ACTION_CHECK_IP_ADDRESS));
|
|
||||||
return Unit.INSTANCE;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void launchTetheringSettingsScreen() {
|
private void launchTetheringSettingsScreen() {
|
||||||
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
|
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
|
||||||
intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||||
@ -324,19 +264,6 @@ public class ZimHostActivity extends BaseActivity implements
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onHotspotFailedToStart() {
|
|
||||||
//Show a dialog to turn off default hotspot
|
|
||||||
alertDialogShower.show(KiwixDialog.TurnOffHotspotManually.INSTANCE,
|
|
||||||
(Function0<Unit>) () -> {
|
|
||||||
launchTetheringSettingsScreen();
|
|
||||||
return Unit.INSTANCE;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void requestLocationAccess() {
|
|
||||||
locationServicesHelper.setupLocationServices();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected void onSaveInstanceState(@Nullable Bundle outState) {
|
@Override protected void onSaveInstanceState(@Nullable Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
if (ServerUtils.isServerStarted) {
|
if (ServerUtils.isServerStarted) {
|
||||||
@ -348,10 +275,6 @@ public class ZimHostActivity extends BaseActivity implements
|
|||||||
booksAdapter.setItems(books);
|
booksAdapter.setItems(books);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onLocationSet() {
|
|
||||||
startService(createHotspotIntent(ACTION_LOCATION_ACCESS_GRANTED));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onIpAddressValid() {
|
@Override public void onIpAddressValid() {
|
||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
startService(createHotspotIntent(ACTION_START_SERVER).putStringArrayListExtra(
|
startService(createHotspotIntent(ACTION_START_SERVER).putStringArrayListExtra(
|
||||||
|
@ -11,12 +11,6 @@ public interface ZimHostCallbacks {
|
|||||||
|
|
||||||
void onServerFailedToStart();
|
void onServerFailedToStart();
|
||||||
|
|
||||||
void onHotspotTurnedOn(@NonNull WifiConfiguration wifiConfiguration);
|
|
||||||
|
|
||||||
void onHotspotFailedToStart();
|
|
||||||
|
|
||||||
void requestLocationAccess();
|
|
||||||
|
|
||||||
void onIpAddressValid();
|
void onIpAddressValid();
|
||||||
|
|
||||||
void onIpAddressInvalid();
|
void onIpAddressInvalid();
|
||||||
|
@ -18,16 +18,5 @@ public class ZimHostModule {
|
|||||||
@Provides Activity providesActivity(ZimHostActivity zimHostActivity) {
|
@Provides Activity providesActivity(ZimHostActivity zimHostActivity) {
|
||||||
return zimHostActivity;
|
return zimHostActivity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ActivityScope
|
|
||||||
@Provides LocationServicesHelper providesLocationServicesHelper(ZimHostActivity activity,
|
|
||||||
LocationCallbacks locationCallbacks) {
|
|
||||||
return new LocationServicesHelper(activity, locationCallbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ActivityScope
|
|
||||||
@Provides LocationCallbacks providesLocationCallbacks(ZimHostActivity activity) {
|
|
||||||
return activity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,7 @@ package org.kiwix.kiwixmobile.wifi_hotspot;
|
|||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.wifi.WifiConfiguration;
|
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -12,6 +10,7 @@ import androidx.annotation.Nullable;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.kiwix.kiwixmobile.KiwixApplication;
|
import org.kiwix.kiwixmobile.KiwixApplication;
|
||||||
import org.kiwix.kiwixmobile.R;
|
import org.kiwix.kiwixmobile.R;
|
||||||
|
import org.kiwix.kiwixmobile.extensions.ContextExtensionsKt;
|
||||||
import org.kiwix.kiwixmobile.utils.ServerUtils;
|
import org.kiwix.kiwixmobile.utils.ServerUtils;
|
||||||
import org.kiwix.kiwixmobile.webserver.WebServerHelper;
|
import org.kiwix.kiwixmobile.webserver.WebServerHelper;
|
||||||
import org.kiwix.kiwixmobile.webserver.ZimHostCallbacks;
|
import org.kiwix.kiwixmobile.webserver.ZimHostCallbacks;
|
||||||
@ -24,10 +23,9 @@ import static org.kiwix.kiwixmobile.wifi_hotspot.HotspotNotificationManager.HOTS
|
|||||||
* Created by Adeel Zafar on 07/01/2019.
|
* Created by Adeel Zafar on 07/01/2019.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HotspotService extends Service implements HotspotStateListener, IpAddressCallbacks {
|
public class HotspotService extends Service
|
||||||
|
implements IpAddressCallbacks, HotspotStateReceiver.Callback {
|
||||||
|
|
||||||
public static final String ACTION_TOGGLE_HOTSPOT = "toggle_hotspot";
|
|
||||||
public static final String ACTION_LOCATION_ACCESS_GRANTED = "location_access_granted";
|
|
||||||
public static final String ACTION_START_SERVER = "start_server";
|
public static final String ACTION_START_SERVER = "start_server";
|
||||||
public static final String ACTION_STOP_SERVER = "stop_server";
|
public static final String ACTION_STOP_SERVER = "stop_server";
|
||||||
public static final String ACTION_CHECK_IP_ADDRESS = "check_ip_address";
|
public static final String ACTION_CHECK_IP_ADDRESS = "check_ip_address";
|
||||||
@ -38,9 +36,9 @@ public class HotspotService extends Service implements HotspotStateListener, IpA
|
|||||||
@Inject
|
@Inject
|
||||||
WebServerHelper webServerHelper;
|
WebServerHelper webServerHelper;
|
||||||
@Inject
|
@Inject
|
||||||
WifiHotspotManager hotspotManager;
|
|
||||||
@Inject
|
|
||||||
HotspotNotificationManager hotspotNotificationManager;
|
HotspotNotificationManager hotspotNotificationManager;
|
||||||
|
@Inject
|
||||||
|
HotspotStateReceiver hotspotStateReceiver;
|
||||||
|
|
||||||
@Override public void onCreate() {
|
@Override public void onCreate() {
|
||||||
KiwixApplication.getApplicationComponent()
|
KiwixApplication.getApplicationComponent()
|
||||||
@ -49,50 +47,27 @@ public class HotspotService extends Service implements HotspotStateListener, IpA
|
|||||||
.build()
|
.build()
|
||||||
.inject(this);
|
.inject(this);
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
ContextExtensionsKt.registerReceiver(this, hotspotStateReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void onDestroy() {
|
||||||
|
unregisterReceiver(hotspotStateReceiver);
|
||||||
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int onStartCommand(@NonNull Intent intent, int flags, int startId) {
|
@Override public int onStartCommand(@NonNull Intent intent, int flags, int startId) {
|
||||||
switch (intent.getAction()) {
|
switch (intent.getAction()) {
|
||||||
|
|
||||||
case ACTION_TOGGLE_HOTSPOT:
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
if (hotspotManager.isHotspotStarted()) {
|
|
||||||
stopHotspotAndDismissNotification();
|
|
||||||
} else {
|
|
||||||
if (zimHostCallbacks != null) {
|
|
||||||
zimHostCallbacks.requestLocationAccess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACTION_LOCATION_ACCESS_GRANTED:
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
hotspotManager.turnOnHotspot();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACTION_START_SERVER:
|
case ACTION_START_SERVER:
|
||||||
if (webServerHelper.startServerHelper(
|
if (webServerHelper.startServerHelper(
|
||||||
intent.getStringArrayListExtra(SELECTED_ZIM_PATHS_KEY))) {
|
intent.getStringArrayListExtra(SELECTED_ZIM_PATHS_KEY))) {
|
||||||
if (zimHostCallbacks != null) {
|
|
||||||
zimHostCallbacks.onServerStarted(ServerUtils.getSocketAddress());
|
zimHostCallbacks.onServerStarted(ServerUtils.getSocketAddress());
|
||||||
}
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
|
||||||
startForegroundNotificationHelper();
|
startForegroundNotificationHelper();
|
||||||
}
|
|
||||||
Toast.makeText(this, R.string.server_started__successfully_toast_message,
|
Toast.makeText(this, R.string.server_started__successfully_toast_message,
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
if (zimHostCallbacks != null) {
|
|
||||||
zimHostCallbacks.onServerFailedToStart();
|
zimHostCallbacks.onServerFailedToStart();
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
stopForeground(true);
|
|
||||||
stopSelf();
|
|
||||||
hotspotNotificationManager.dismissNotification();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -116,9 +91,6 @@ public class HotspotService extends Service implements HotspotStateListener, IpA
|
|||||||
|
|
||||||
//Dismiss notification and turn off hotspot for devices>=O
|
//Dismiss notification and turn off hotspot for devices>=O
|
||||||
private void stopHotspotAndDismissNotification() {
|
private void stopHotspotAndDismissNotification() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
hotspotManager.turnOffHotspot();
|
|
||||||
} else {
|
|
||||||
webServerHelper.stopAndroidWebServer();
|
webServerHelper.stopAndroidWebServer();
|
||||||
if (zimHostCallbacks != null) {
|
if (zimHostCallbacks != null) {
|
||||||
zimHostCallbacks.onServerStopped();
|
zimHostCallbacks.onServerStopped();
|
||||||
@ -127,7 +99,6 @@ public class HotspotService extends Service implements HotspotStateListener, IpA
|
|||||||
stopSelf();
|
stopSelf();
|
||||||
hotspotNotificationManager.dismissNotification();
|
hotspotNotificationManager.dismissNotification();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void registerCallBack(@Nullable ZimHostCallbacks myCallback) {
|
public void registerCallBack(@Nullable ZimHostCallbacks myCallback) {
|
||||||
zimHostCallbacks = myCallback;
|
zimHostCallbacks = myCallback;
|
||||||
@ -138,29 +109,6 @@ public class HotspotService extends Service implements HotspotStateListener, IpA
|
|||||||
hotspotNotificationManager.buildForegroundNotification());
|
hotspotNotificationManager.buildForegroundNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onHotspotTurnedOn(@NonNull WifiConfiguration wifiConfiguration) {
|
|
||||||
startForegroundNotificationHelper();
|
|
||||||
if (zimHostCallbacks != null) {
|
|
||||||
zimHostCallbacks.onHotspotTurnedOn(wifiConfiguration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onHotspotFailedToStart() {
|
|
||||||
if (zimHostCallbacks != null) {
|
|
||||||
zimHostCallbacks.onHotspotFailedToStart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onHotspotStopped() {
|
|
||||||
webServerHelper.stopAndroidWebServer();
|
|
||||||
if (zimHostCallbacks != null) {
|
|
||||||
zimHostCallbacks.onServerStopped();
|
|
||||||
}
|
|
||||||
stopForeground(true);
|
|
||||||
stopSelf();
|
|
||||||
hotspotNotificationManager.dismissNotification();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onIpAddressValid() {
|
@Override public void onIpAddressValid() {
|
||||||
if (zimHostCallbacks != null) {
|
if (zimHostCallbacks != null) {
|
||||||
zimHostCallbacks.onIpAddressValid();
|
zimHostCallbacks.onIpAddressValid();
|
||||||
@ -173,6 +121,10 @@ public class HotspotService extends Service implements HotspotStateListener, IpA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void onHotspotDisabled() {
|
||||||
|
stopHotspotAndDismissNotification();
|
||||||
|
}
|
||||||
|
|
||||||
public class HotspotBinder extends Binder {
|
public class HotspotBinder extends Binder {
|
||||||
|
|
||||||
@NonNull public HotspotService getService() {
|
@NonNull public HotspotService getService() {
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
package org.kiwix.kiwixmobile.wifi_hotspot;
|
|
||||||
|
|
||||||
import android.net.wifi.WifiConfiguration;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public interface HotspotStateListener {
|
|
||||||
void onHotspotTurnedOn(@NonNull WifiConfiguration wifiConfiguration);
|
|
||||||
|
|
||||||
void onHotspotFailedToStart();
|
|
||||||
|
|
||||||
void onHotspotStopped();
|
|
||||||
}
|
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (C) 2018 Kiwix <android.kiwix.org>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
package org.kiwix.kiwixmobile.wifi_hotspot
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import org.kiwix.kiwixmobile.wifi_hotspot.HotspotStateReceiver.HotspotState.DISABLED
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.BaseBroadcastReceiver
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
const val EXTRA_WIFI_AP_STATE = "wifi_state"
|
||||||
|
const val ACTION_WIFI_AP_STATE = "android.net.wifi.WIFI_AP_STATE_CHANGED"
|
||||||
|
|
||||||
|
const val WIFI_AP_STATE_DISABLING = 10
|
||||||
|
const val WIFI_AP_STATE_DISABLED = 11
|
||||||
|
const val WIFI_AP_STATE_ENABLING = 12
|
||||||
|
const val WIFI_AP_STATE_ENABLED = 13
|
||||||
|
const val WIFI_AP_STATE_FAILED = 14
|
||||||
|
|
||||||
|
class HotspotStateReceiver @Inject constructor(val callback: Callback) : BaseBroadcastReceiver() {
|
||||||
|
override val action: String = ACTION_WIFI_AP_STATE
|
||||||
|
|
||||||
|
override fun onIntentWithActionReceived(context: Context, intent: Intent) {
|
||||||
|
if (DISABLED == hotspotState(intent)) {
|
||||||
|
callback.onHotspotDisabled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hotspotState(intent: Intent) =
|
||||||
|
HotspotState.from(intent.getIntExtra(EXTRA_WIFI_AP_STATE, -1))
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun onHotspotDisabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum class HotspotState(val state: Int) {
|
||||||
|
|
||||||
|
DISABLING(WIFI_AP_STATE_DISABLING),
|
||||||
|
DISABLED(WIFI_AP_STATE_DISABLED),
|
||||||
|
ENABLING(WIFI_AP_STATE_ENABLING),
|
||||||
|
ENABLED(WIFI_AP_STATE_ENABLED),
|
||||||
|
FAILED(WIFI_AP_STATE_FAILED);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun from(state: Int) = HotspotState.values().firstOrNull { state == it.state }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,86 +0,0 @@
|
|||||||
package org.kiwix.kiwixmobile.wifi_hotspot;
|
|
||||||
|
|
||||||
import android.net.wifi.WifiConfiguration;
|
|
||||||
import android.net.wifi.WifiManager;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WifiHotstopManager class makes use of the Android's WifiManager and WifiConfiguration class
|
|
||||||
* to implement the wifi hotspot feature.
|
|
||||||
* Created by Adeel Zafar on 28/5/2019.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class WifiHotspotManager {
|
|
||||||
private static final String TAG = "WifiHotspotManager";
|
|
||||||
private WifiManager wifiManager;
|
|
||||||
private WifiManager.LocalOnlyHotspotReservation hotspotReservation;
|
|
||||||
private HotspotStateListener hotspotStateListener;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public WifiHotspotManager(@NonNull WifiManager wifiManager,
|
|
||||||
@NonNull HotspotStateListener hotspotStateListener) {
|
|
||||||
this.wifiManager = wifiManager;
|
|
||||||
this.hotspotStateListener = hotspotStateListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Workaround to turn on hotspot for Oreo versions
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
||||||
public void turnOnHotspot() {
|
|
||||||
wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
|
|
||||||
super.onStarted(reservation);
|
|
||||||
hotspotReservation = reservation;
|
|
||||||
WifiConfiguration currentConfig = hotspotReservation.getWifiConfiguration();
|
|
||||||
|
|
||||||
printCurrentConfig(currentConfig);
|
|
||||||
hotspotStateListener.onHotspotTurnedOn(currentConfig);
|
|
||||||
Log.v(TAG, "Local Hotspot Started");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStopped() {
|
|
||||||
super.onStopped();
|
|
||||||
hotspotStateListener.onHotspotStopped();
|
|
||||||
Log.v(TAG, "Local Hotspot Stopped");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed(int reason) {
|
|
||||||
super.onFailed(reason);
|
|
||||||
hotspotStateListener.onHotspotFailedToStart();
|
|
||||||
Log.v(TAG, "Local Hotspot failed to start");
|
|
||||||
}
|
|
||||||
}, new Handler());
|
|
||||||
}
|
|
||||||
|
|
||||||
//Workaround to turn off hotspot for Oreo versions
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
||||||
public void turnOffHotspot() {
|
|
||||||
if (hotspotReservation != null) {
|
|
||||||
hotspotReservation.close();
|
|
||||||
hotspotReservation = null;
|
|
||||||
hotspotStateListener.onHotspotStopped();
|
|
||||||
Log.v(TAG, "Turned off hotspot");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//This method checks the state of the hostpot for devices>=Oreo
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
||||||
public boolean isHotspotStarted() {
|
|
||||||
return hotspotReservation != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void printCurrentConfig(WifiConfiguration wifiConfiguration) {
|
|
||||||
Log.v(TAG, "THE PASSWORD IS: "
|
|
||||||
+ wifiConfiguration.preSharedKey
|
|
||||||
+ " \n SSID is : "
|
|
||||||
+ wifiConfiguration.SSID);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user