Integrate kiwix-serve

Pass selected Zim Paths to HotspotService
Starting/stopping server in WebServerHelper
Refactor startWebServerHelper()
Add check for no books selected
Refactor foreground notification
Remove updateNotification
This commit is contained in:
Adeel Zafar 2019-08-15 01:55:54 +05:00
parent d1bfa65790
commit ca12e17910
8 changed files with 96 additions and 53 deletions

1
.gitignore vendored
View File

@ -66,3 +66,4 @@ captures/
!/.idea/encodings.xml !/.idea/encodings.xml
!/.idea/copyright/ !/.idea/copyright/
!/.idea/compiler.xml !/.idea/compiler.xml
app/libs

View File

@ -17,6 +17,8 @@
*/ */
package org.kiwix.kiwixmobile.di.modules; package org.kiwix.kiwixmobile.di.modules;
import android.content.Context;
import androidx.annotation.NonNull;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -29,7 +31,7 @@ import org.kiwix.kiwixlib.JNIKiwix;
@Module public class JNIModule { @Module public class JNIModule {
@Provides @Provides
@Singleton @Singleton
public JNIKiwix providesJNIKiwix() { public JNIKiwix providesJNIKiwix(@NonNull Context context) {
return new JNIKiwix(); return new JNIKiwix(context);
} }
} }

View File

@ -1,10 +1,15 @@
package org.kiwix.kiwixmobile.webserver; package org.kiwix.kiwixmobile.webserver;
import android.content.Context; import android.content.Context;
import android.util.Log;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.SocketException; import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import org.kiwix.kiwixlib.JNIKiwixException;
import org.kiwix.kiwixlib.JNIKiwixLibrary;
import org.kiwix.kiwixlib.JNIKiwixServer;
/** /**
* WebServerHelper class is used to set up the suitable environment i.e. getting the * WebServerHelper class is used to set up the suitable environment i.e. getting the
@ -16,32 +21,34 @@ public class WebServerHelper {
Context context; Context context;
public static boolean isServerStarted; public static boolean isServerStarted;
static int port; static int port;
JNIKiwixLibrary kiwixLibrary = new JNIKiwixLibrary();
JNIKiwixServer kiwixServer = new JNIKiwixServer(kiwixLibrary);
private static final String TAG = "WebServerHelper";
public WebServerHelper(Context context) { public WebServerHelper(Context context) {
this.context = context; this.context = context;
} }
public void startServerHelper(ServerStateListener stateListener) { public boolean startServerHelper(ServerStateListener stateListener,
ArrayList<String> selectedBooksPath) {
// 1. Get port from settings screen // 1. Get port from settings screen
// 2. Ask user to change port in settings if port is in use. // 2. Ask user to change port in settings if port is in use.
// OR // OR
// Always use 8080 and when its not available then iterate this number. // Always use 8080 and when its not available then iterate this number.
String ip = getIpAddress();
if (!isServerStarted && startAndroidWebServer()) { ip = ip.replaceAll("\n", "");
isServerStarted = true; if (ip.length() == 0) {
String ip = getIpAddress(); stateListener.serverFailed();
ip = ip.replaceAll("\n", ""); } else if (!isServerStarted && startAndroidWebServer(selectedBooksPath)) {
if (ip.length() == 0) { stateListener.serverStarted("http://" + ip + ":" + port);
stateListener.serverFailed();
} else {
stateListener.serverStarted("http://" + ip + ":" + port);
}
} }
return isServerStarted;
} }
public static boolean stopAndroidWebServer(ServerStateListener stateListener) { public boolean stopAndroidWebServer(ServerStateListener stateListener) {
if (isServerStarted) { if (isServerStarted) {
kiwixServer.stop();
isServerStarted = false; isServerStarted = false;
stateListener.serverStopped(); stateListener.serverStopped();
return true; return true;
@ -49,13 +56,23 @@ public class WebServerHelper {
return false; return false;
} }
boolean startAndroidWebServer() { boolean startAndroidWebServer(ArrayList<String> selectedBooksPath) {
if (!isServerStarted) { if (!isServerStarted) {
port = 8080; port = 8080;
//Call to start server //Call to start server
return true; for (String path : selectedBooksPath) {
try {
boolean isBookAdded = kiwixLibrary.addBook(path);
Log.v(TAG, "Book added:" + path);
} catch (JNIKiwixException e) {
Log.v(TAG, "Couldn't add book " + path);
}
}
kiwixServer.setPort(port);
isServerStarted = kiwixServer.start();
Log.v(TAG, "Server status" + isServerStarted);
} }
return false; return isServerStarted;
} }
// get Ip address of the device's wireless access point i.e. wifi hotspot OR wifi network // get Ip address of the device's wireless access point i.e. wifi hotspot OR wifi network

View File

@ -74,6 +74,7 @@ public class ZimHostActivity extends BaseActivity implements
public static final String ACTION_IS_HOTSPOT_ENABLED = "Is_hotspot_enabled"; public static final String ACTION_IS_HOTSPOT_ENABLED = "Is_hotspot_enabled";
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 SELECTED_ZIM_PATHS_KEY = "selected_zim_paths";
private static final String IP_STATE_KEY = "ip_state_key"; private static final String IP_STATE_KEY = "ip_state_key";
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 int MY_PERMISSIONS_ACCESS_FINE_LOCATION = 102;
@ -146,28 +147,38 @@ public class ZimHostActivity extends BaseActivity implements
startServerButton.setOnClickListener(new View.OnClickListener() { startServerButton.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) { @Override public void onClick(View v) {
//Get File Path of All The ZIMs using booksAdapter //Get the path of ZIMs user has selected
if (!isServerStarted) {
getSelectedBooksPath(); getSelectedBooksPath();
if (selectedBooksPath.size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startHotspotHelper();
toggleHotspot();
} else {
//TO DO: show Dialog() + within that add check mobile Data check later.
//if (isMobileDataEnabled(context)) {
// mobileDataDialog();
//} else {
if (isServerStarted) {
startService(ACTION_STOP_SERVER);
} else { } else {
startHotspotDialog(); Toast.makeText(ZimHostActivity.this, R.string.no_books_selected_toast_message,
Toast.LENGTH_SHORT).show();
} }
//} } else {
startHotspotHelper();
} }
} }
}); });
} }
void startHotspotHelper() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
toggleHotspot();
} else {
//TO DO: show Dialog() + within that add check mobile Data check later.
//if (isMobileDataEnabled(context)) {
// mobileDataDialog();
//} else {
if (isServerStarted) {
startService(ACTION_STOP_SERVER);
} else {
startHotspotDialog();
}
//}
}
}
void getSelectedBooksPath() { void getSelectedBooksPath() {
BooksOnDiskListItem.BookOnDisk bookOnDisk; BooksOnDiskListItem.BookOnDisk bookOnDisk;
@ -191,13 +202,15 @@ public class ZimHostActivity extends BaseActivity implements
public void select(BooksOnDiskListItem.BookOnDisk bookOnDisk) { public void select(BooksOnDiskListItem.BookOnDisk bookOnDisk) {
ArrayList<BooksOnDiskListItem> booksList = new ArrayList<>(); ArrayList<BooksOnDiskListItem> booksList = new ArrayList<>();
booksList.addAll(booksAdapter.getItems());
int i = 0;
for (BooksOnDiskListItem item : booksAdapter.getItems()) { for (BooksOnDiskListItem item : booksAdapter.getItems()) {
if (item.equals(bookOnDisk)) { if (item.equals(bookOnDisk)) {
booksList.get(i).setSelected(!bookOnDisk.isSelected()); if (item.isSelected()) {
item.setSelected(false);
} else {
item.setSelected(true);
}
} }
i++; booksList.add(item);
} }
booksAdapter.setItems(booksList); booksAdapter.setItems(booksList);
} }
@ -422,6 +435,9 @@ public class ZimHostActivity extends BaseActivity implements
} }
void startService(String ACTION) { void startService(String ACTION) {
if (ACTION.equals(ACTION_START_SERVER)) {
serviceIntent.putStringArrayListExtra(SELECTED_ZIM_PATHS_KEY, selectedBooksPath);
}
serviceIntent.setAction(ACTION); serviceIntent.setAction(ACTION);
this.startService(serviceIntent); this.startService(serviceIntent);
} }
@ -482,7 +498,6 @@ public class ZimHostActivity extends BaseActivity implements
public void run() { public void run() {
progressDialog.dismiss(); progressDialog.dismiss();
startService(ACTION_START_SERVER); startService(ACTION_START_SERVER);
//webServerHelper.startServerHelper();
} }
}, 2000); }, 2000);
}); });
@ -496,6 +511,8 @@ public class ZimHostActivity extends BaseActivity implements
builder.setCancelable(false); builder.setCancelable(false);
AlertDialog dialog = builder.create(); AlertDialog dialog = builder.create();
dialog.show(); dialog.show();
//setupServer();
} }
private void setupWifiSettingsIntent() { private void setupWifiSettingsIntent() {

View File

@ -13,8 +13,8 @@ import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import org.kiwix.kiwixmobile.R; import org.kiwix.kiwixmobile.R;
import org.kiwix.kiwixmobile.utils.Constants; import org.kiwix.kiwixmobile.utils.Constants;
@ -27,6 +27,7 @@ import static org.kiwix.kiwixmobile.webserver.ZimHostActivity.ACTION_START_SERVE
import static org.kiwix.kiwixmobile.webserver.ZimHostActivity.ACTION_STOP_SERVER; import static org.kiwix.kiwixmobile.webserver.ZimHostActivity.ACTION_STOP_SERVER;
import static org.kiwix.kiwixmobile.webserver.ZimHostActivity.ACTION_TURN_OFF_AFTER_O; import static org.kiwix.kiwixmobile.webserver.ZimHostActivity.ACTION_TURN_OFF_AFTER_O;
import static org.kiwix.kiwixmobile.webserver.ZimHostActivity.ACTION_TURN_ON_AFTER_O; import static org.kiwix.kiwixmobile.webserver.ZimHostActivity.ACTION_TURN_ON_AFTER_O;
import static org.kiwix.kiwixmobile.webserver.ZimHostActivity.SELECTED_ZIM_PATHS_KEY;
/** /**
* HotspotService is used to add a foreground service for the wifi hotspot. * HotspotService is used to add a foreground service for the wifi hotspot.
@ -65,8 +66,6 @@ public class HotspotService extends Service {
webServerHelper = new WebServerHelper(this); webServerHelper = new WebServerHelper(this);
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
startForeground(HOTSPOT_NOTIFICATION_ID,
buildForegroundNotification(getString(R.string.hotspot_start), false));
} }
@Override public int onStartCommand(Intent intent, int flags, int startId) { @Override public int onStartCommand(Intent intent, int flags, int startId) {
@ -80,9 +79,9 @@ public class HotspotService extends Service {
case ACTION_TURN_ON_AFTER_O: case ACTION_TURN_ON_AFTER_O:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//serverStateListener.hotspotTurnedOn(hotspotManager.turnOnHotspot());
hotspotManager.turnOnHotspot(serverStateListener); hotspotManager.turnOnHotspot(serverStateListener);
updateNotification(getString(R.string.hotspot_running), true); startForeground(HOTSPOT_NOTIFICATION_ID,
buildForegroundNotification(getString(R.string.hotspot_running), true));
} }
break; break;
@ -93,10 +92,18 @@ public class HotspotService extends Service {
break; break;
case ACTION_START_SERVER: case ACTION_START_SERVER:
webServerHelper.startServerHelper(serverStateListener); if (!webServerHelper.startServerHelper(serverStateListener,
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { intent.getStringArrayListExtra(SELECTED_ZIM_PATHS_KEY))) {
updateNotification(getString(R.string.hotspot_running), true); Toast.makeText(this, R.string.server_failed_toast_message, Toast.LENGTH_LONG).show();
} else {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
startForeground(HOTSPOT_NOTIFICATION_ID,
buildForegroundNotification(getString(R.string.hotspot_running), true));
}
Toast.makeText(this, R.string.server_started__successfully_toast_message,
Toast.LENGTH_LONG).show();
} }
break; break;
case ACTION_STOP_SERVER: case ACTION_STOP_SERVER:
@ -136,11 +143,6 @@ public class HotspotService extends Service {
return (builder.build()); return (builder.build());
} }
private void updateNotification(String status, boolean stopAction) {
notificationManager.notify(HOTSPOT_NOTIFICATION_ID,
buildForegroundNotification(status, stopAction));
}
//Dismiss notification and turn off hotspot for devices>=O //Dismiss notification and turn off hotspot for devices>=O
void stopHotspotAndDismissNotification() { void stopHotspotAndDismissNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

View File

@ -31,7 +31,6 @@ public class WifiHotspotManager {
//Workaround to turn on hotspot for Oreo versions //Workaround to turn on hotspot for Oreo versions
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
public void turnOnHotspot(ServerStateListener serverStateListener) { public void turnOnHotspot(ServerStateListener serverStateListener) {
if (!isHotspotEnabled) {
wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() { wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
@Override @Override
@ -48,6 +47,8 @@ public class WifiHotspotManager {
serverStateListener.hotspotTurnedOn(currentConfig); serverStateListener.hotspotTurnedOn(currentConfig);
isHotspotEnabled = true; isHotspotEnabled = true;
Log.v(TAG, "Is hotspot enabled? " + isHotspotEnabled);
} }
@Override @Override
@ -62,9 +63,10 @@ public class WifiHotspotManager {
super.onFailed(reason); super.onFailed(reason);
Log.v(TAG, "Local Hotspot failed to start"); Log.v(TAG, "Local Hotspot failed to start");
serverStateListener.hotspotFailed(); serverStateListener.hotspotFailed();
isHotspotEnabled = false;
Log.v(TAG, "Is hotspot enabled? " + isHotspotEnabled);
} }
}, new Handler()); }, new Handler());
}
} }
//Workaround to turn off hotspot for Oreo versions //Workaround to turn off hotspot for Oreo versions

View File

@ -159,4 +159,3 @@ class ZimFileSelectFragment : BaseFragment() {
zimManageViewModel.requestFileSystemCheck.onNext(Unit) zimManageViewModel.requestFileSystemCheck.onNext(Unit)
} }
} }

View File

@ -31,7 +31,10 @@
<string name="hotspot_start">Starting hotspot</string> <string name="hotspot_start">Starting hotspot</string>
<string name="hotspot_running">Running Hotspot</string> <string name="hotspot_running">Running Hotspot</string>
<string name="stop_hotspot_button">STOP</string> <string name="stop_hotspot_button">STOP</string>
<string name="no_books_selected_toast_message">Please select books first</string>
<string name="server_failed_message">Couldnt start server. Please turn on your hotspot</string> <string name="server_failed_message">Couldnt start server. Please turn on your hotspot</string>
<string name="server_failed_toast_message">Couldnt start server.</string>
<string name="server_started__successfully_toast_message">Server started successfully.</string>
<string name="hotspot_turned_on">Hotspot turned on</string> <string name="hotspot_turned_on">Hotspot turned on</string>
<string name="hotspot_details_message">Following are the details of your local hotspot.</string> <string name="hotspot_details_message">Following are the details of your local hotspot.</string>
<string name="hotspot_ssid_label">SSID : </string> <string name="hotspot_ssid_label">SSID : </string>