Merge pull request #1506 from kiwix/iadeelzafar/manual-hotspot

Iadeelzafar/manual hotspot
This commit is contained in:
Seán Mac Gillicuddy 2019-09-23 15:33:22 +01:00 committed by GitHub
commit f9e722f72f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 102 additions and 402 deletions

View File

@ -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" />

View File

@ -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
} }

View File

@ -1,5 +0,0 @@
package org.kiwix.kiwixmobile.webserver;
public interface LocationCallbacks {
void onLocationSet();
}

View File

@ -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;
}
}
}
}

View File

@ -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,15 +121,11 @@ 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() {
@ -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(

View File

@ -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();

View File

@ -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;
}
} }

View File

@ -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,49 +47,26 @@ 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()); startForegroundNotificationHelper();
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
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,17 +91,13 @@ 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) { webServerHelper.stopAndroidWebServer();
hotspotManager.turnOffHotspot(); if (zimHostCallbacks != null) {
} else { zimHostCallbacks.onServerStopped();
webServerHelper.stopAndroidWebServer();
if (zimHostCallbacks != null) {
zimHostCallbacks.onServerStopped();
}
stopForeground(true);
stopSelf();
hotspotNotificationManager.dismissNotification();
} }
stopForeground(true);
stopSelf();
hotspotNotificationManager.dismissNotification();
} }
public void registerCallBack(@Nullable ZimHostCallbacks myCallback) { public void registerCallBack(@Nullable 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() {

View File

@ -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();
}

View File

@ -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 }
}
}
}

View File

@ -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);
}
}