Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Offline #2

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
17 changes: 15 additions & 2 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.microg.nlp.backend.openwlanmap">
package="org.microg.nlp.backend.openwlanmap"
android:versionCode="2"
android:versionName="0.0.2"
>

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-sdk android:minSdkVersion="19" />
<application
Expand All @@ -19,7 +23,16 @@
<intent-filter>
<action android:name="org.microg.nlp.LOCATION_BACKEND" />
</intent-filter>
<meta-data
android:name="org.microg.nlp.BACKEND_SETTINGS_ACTIVITY"
android:value="org.microg.nlp.backend.openwlanmap.local.Settings" />
</service>

<activity android:name="org.microg.nlp.backend.openwlanmap.local.Settings"
android:label="OpenWlanMap Backend">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes it visible by the standard Android launcher. If you leave this off it will only be accessible via the settings menu in NLP (which is what my latest changes to my GSM location back end do.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Once you add the meta-data BACKEND_SETTINGS_ACTIVITY (as you did) and mark the activity as exported using android:exported="true" (which you missed out) it will show up in the UnifiedNlp settings in the overflow menu next to the backend. There is no reason to show a feature in the launcher, the user merely uses.

</intent-filter>
</activity>
</application>
</manifest>
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ OpenWlanMapNlpBackend
=====================
[UnifiedNlp](https://github.com/microg/android_packages_apps_UnifiedNlp) backend that uses [OpenWlanMap](http://www.openwlanmap.org/) to resolve user location.

Location calculation is done online and therefor requires internet connection.
Location calculation is done either online or offline. This can be switched in the settings.
Online calculation of course requires internet connection.
Offline calculation won't use any data, but look up the wifi access points in a database on your sd-card only.
To generate the database a shell script (gen_openwifimap_db.sh) is included.

To contribute to the OpenWlanMap database you can use the available Android app or upload your "wardriving" data manually [here](https://openwlanmap.org/upload.php?lang=). Don't forget to enable the "Publish own data" in the Android apps settings!

Building
--------
Expand All @@ -16,6 +21,13 @@ Used libraries
- [libwlocate](http://sourceforge.net/projects/libwlocate/) (included)


Changes
-------

0.0.2 - Felix Knecht added offline support

0.0.1 - Initial version by @mar-v-in with online support

License
-------
libwlocate is GPLv3, so is OpenWlanMapNlpBackend.
Expand Down
45 changes: 45 additions & 0 deletions gen_openwifimap_db.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#! /bin/bash
#
# Quick and dirty script to build and install a new
# wifi APs location database on a phone for microg/nogapps
# OpenWlanMapNlpBackend.
#


#
# Get latest wifi AP locations from OpenWLANMap.org
#
echo 'Getting wifi AP locations from OpenWLANMap.org'
if [ -e db.tar.bz2 ] ; then
rm db.tar.bz2
fi
if [ -e db.csv ] ; then
mv -f db.csv db.csv.bak
fi
wget "http://openwlanmap.org/db.tar.bz2"
tar --strip-components=1 -xjf db.tar.bz2 db/db.csv


echo 'Building database file'
if [ -e openwifimap.db ] ; then
mv -f openwifimap.db openwifimap.db.bak
fi

### TODO: Filter all entries with lat or long = 0
### Those are the _nomap entries

sqlite3 openwifimap.db <<!
CREATE TABLE APs(bssid STRING, latitude REAL, longitude REAL);
.mode csv
.separator "\t"
.import db.csv APs
CREATE INDEX _idx1 ON APs (bssid);
VACUUM;
.quit
!

#
# Push the new database to the phone.
#
echo 'Pushing database to phone'
adb push openwifimap.db /sdcard/.nogapps/openwifimap.db
7 changes: 7 additions & 0 deletions res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">OpenWlanMapNlpBackend</string>
<string name="title_network_category">Network</string>
<string name="title_networkAllowed_preference">Allow network activity</string>
<string name="title_local_category">Local</string>
<string name="title_databaseLocation_preference">Database location</string>
<string name="title_assumedAccuracy_preference">Assumed accuracy for database in meters</string>

<string name="prefs_error_accuracy_notfloat">The supplied value for assumed accuracy is not a float</string>
</resources>
20 changes: 20 additions & 0 deletions res/xml/settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

<PreferenceCategory android:title="@string/title_network_category" >
<CheckBoxPreference
android:key="networkAllowed"
android:title="@string/title_networkAllowed_preference" />
</PreferenceCategory>

<PreferenceCategory android:title="@string/title_local_category"
android:key="category_local">
<EditTextPreference
android:key="databaseLocation"
android:title="@string/title_databaseLocation_preference" />
<EditTextPreference
android:defaultValue="50"
android:numeric="integer"
android:key="assumedAccuracy"
android:title="@string/title_assumedAccuracy_preference" />
</PreferenceCategory>
</PreferenceScreen>
102 changes: 96 additions & 6 deletions src/org/microg/nlp/backend/openwlanmap/BackendService.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,92 @@
package org.microg.nlp.backend.openwlanmap;

import java.util.ArrayList;
import java.util.List;

import org.microg.nlp.api.LocationBackendService;
import org.microg.nlp.api.LocationHelper;
import org.microg.nlp.backend.openwlanmap.local.WifiLocationFile;
import org.microg.nlp.backend.openwlanmap.local.WifiReceiver;
import org.microg.nlp.backend.openwlanmap.local.WifiReceiver.WifiReceivedCallback;

import android.content.Context;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.location.Location;
import android.net.wifi.WifiManager;
import android.preference.PreferenceManager;
import android.util.Log;

import com.vwp.libwlocate.WLocate;
import org.microg.nlp.api.LocationBackendService;
import org.microg.nlp.api.LocationHelper;

public class BackendService extends LocationBackendService {
private static final String TAG = BackendService.class.getName();
private WLocate wLocate;
private WifiLocationFile wifiLocationFile;
private WifiReceiver wifiReceiver;

@Override
protected void onOpen() {
if (wLocate == null) {
wLocate = new MyWLocate(this);
Log.d(TAG, "onOpen");

SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
Configuration.fillFromPrefs(sharedPrefs);
sharedPrefs.registerOnSharedPreferenceChangeListener(Configuration.listener);

if (Configuration.networkAllowed) {
if (wLocate == null) {
wLocate = new MyWLocate(this);
} else {
wLocate.doResume();
}
} else {
wLocate.doResume();
openDatabase();
if (wifiReceiver == null) {
wifiReceiver = new WifiReceiver(this, new WifiDBResolver());
}
registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
}

@Override
protected void onClose() {
Log.d(TAG, "onClose");

SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
sharedPrefs.unregisterOnSharedPreferenceChangeListener(Configuration.listener);

if (wLocate != null) {
wLocate.doPause();
}
if (wifiReceiver != null) {
unregisterReceiver(wifiReceiver);
}

}

@Override
protected Location update() {
Log.d(TAG, "update");
if (wLocate != null) {
Log.d(TAG, "Requesting location from net");
wLocate.wloc_request_position(WLocate.FLAG_NO_GPS_ACCESS);
return null;
}

if (wifiReceiver != null) {
Log.d(TAG, "Requesting location from db");
wifiReceiver.startScan();
}

return null;
}

private void openDatabase() {
if (wifiLocationFile == null) {
wifiLocationFile = new WifiLocationFile();
}
}

private class MyWLocate extends WLocate {

public MyWLocate(Context ctx) throws IllegalArgumentException {
Expand All @@ -53,4 +105,42 @@ protected void wloc_return_position(int ret, double lat, double lon, float radiu
}
}
}
}

private class WifiDBResolver implements WifiReceivedCallback {

@Override
public void process(List<String> foundBssids) {

if (foundBssids == null || foundBssids.isEmpty()) {
return;
}
if (wifiLocationFile != null) {

List<Location> locations = new ArrayList<Location>(foundBssids.size());

for (String bssid : foundBssids) {
Location result = wifiLocationFile.query(bssid);
if (result != null) {
locations.add(result);
}
}

if (locations.isEmpty()) {
return;
}

//TODO fix LocationHelper:average to not calculate with null values
//TODO sort out wifis obviously in the wrong spot
Location avgLoc = LocationHelper.average("owm", locations);

if (avgLoc == null) {
Log.e(TAG, "Averaging locations did not work.");
return;
}

Log.d(TAG, "Reporting location: " + avgLoc.toString());
report(avgLoc);
}
}
}
}
44 changes: 44 additions & 0 deletions src/org/microg/nlp/backend/openwlanmap/Configuration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.microg.nlp.backend.openwlanmap;

import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Environment;
import android.util.Log;

public class Configuration {
private static String TAG = Configuration.class.getName();

public static boolean networkAllowed;

public static String dbLocation = Environment.getExternalStorageDirectory().getAbsolutePath() + "/.nogapps/openwifimap.db";

public static float assumedAccuracy;

public static ConfigChangedListener listener = new ConfigChangedListener();


public static void fillFromPrefs(SharedPreferences sharedPrefs) {

networkAllowed = sharedPrefs.getBoolean("networkAllowed", false);
Log.d(TAG, "Network allowed: " + networkAllowed);

dbLocation = sharedPrefs.getString("databaseLocation", Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/.nogapps/openwifimap.db");

try {
assumedAccuracy = Float.parseFloat(sharedPrefs.getString("assumedAccuracy", "50"));
} catch (NumberFormatException e) {
assumedAccuracy = 50;
}
}

private static class ConfigChangedListener implements OnSharedPreferenceChangeListener {

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
fillFromPrefs(sharedPreferences);
}
}

}
53 changes: 53 additions & 0 deletions src/org/microg/nlp/backend/openwlanmap/local/PrefsFragment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.microg.nlp.backend.openwlanmap.local;

import org.microg.nlp.backend.openwlanmap.R;

import android.os.Bundle;
import android.os.Environment;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;

public class PrefsFragment extends PreferenceFragment {

public PrefsFragment() {
super();
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);

CheckBoxPreference allowNetwork = (CheckBoxPreference) this.findPreference("networkAllowed");
allowNetwork.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {

return switchLocalGroup((Boolean) newValue);
}
});
//get initial state right
switchLocalGroup(allowNetwork.isChecked());


EditTextPreference dbLocPreference = (EditTextPreference) this.findPreference("databaseLocation");
if (dbLocPreference != null) {
//defaultValue doesn't work very well from code so we fill the pref this way
if (dbLocPreference.getText() == null || dbLocPreference.getText().isEmpty()) {
dbLocPreference.setText(Environment.getExternalStorageDirectory().getAbsolutePath() + "/.nogapps/openwifimap.db");
}
}
}

private boolean switchLocalGroup(boolean networkAllowed) {

PreferenceCategory localCategory = (PreferenceCategory) PrefsFragment.this.findPreference("category_local");
localCategory.setEnabled(!networkAllowed);

return true;
}
}
Loading