{"id":21391932,"url":"https://github.com/mozhiingithub/wifilocation","last_synced_at":"2025-10-10T16:11:36.946Z","repository":{"id":46020923,"uuid":"103822626","full_name":"mozhiingithub/WiFiLocation","owner":"mozhiingithub","description":"一款基于K-NN算法的简易WiFi定位系统SDK","archived":false,"fork":false,"pushed_at":"2020-03-02T12:08:26.000Z","size":78,"stargazers_count":31,"open_issues_count":0,"forks_count":7,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-07T15:52:15.680Z","etag":null,"topics":["java","litepal","location","wifi","wifilocation"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mozhiingithub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-17T11:08:16.000Z","updated_at":"2025-04-04T12:28:01.000Z","dependencies_parsed_at":"2022-07-18T16:28:45.702Z","dependency_job_id":null,"html_url":"https://github.com/mozhiingithub/WiFiLocation","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mozhiingithub/WiFiLocation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozhiingithub%2FWiFiLocation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozhiingithub%2FWiFiLocation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozhiingithub%2FWiFiLocation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozhiingithub%2FWiFiLocation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mozhiingithub","download_url":"https://codeload.github.com/mozhiingithub/WiFiLocation/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozhiingithub%2FWiFiLocation/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265186402,"owners_count":23724658,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","litepal","location","wifi","wifilocation"],"created_at":"2024-11-22T13:38:24.403Z","updated_at":"2025-10-10T16:11:31.926Z","avatar_url":"https://github.com/mozhiingithub.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WiFiLocation\nWiFiLocation是一款基于K-NN算法的简易WiFi定位系统。它借助 **[LitePal](https://github.com/LitePalFramework/LitePal)** 建立本地的WiFi指纹数据库，通过一系列API实现目标地点的WiFi指纹搜集、更新、重置或删除，以及当前位置的定位识别。\n\n相较于传统的C/S架构的WiFi定位系统，本系统实现了完全本地化的运行，所有功能均不会产生任何网络费用。另一方面，完全依赖本地的指纹数据库以及靠手机本身进行定位运算，也大大限制了这款定位系统的定位准确度和效率。\n\n即便性能远不如主流的GPS、移动蜂窝网络及各大地图运营商所提供的在线WiFi室内定位系统，WiFiLocation依旧拥有其独特的使用场景需求：\n#### 1.不借助GPS或蜂窝网络进行常见地点的定位识别\n\n这里所指的常见地点，往往为用户的住处、工作场所或教室。在常见地点有限的前提下，WiFiLocation可以实现与GPS或蜂窝网络大体相近的定位识别而不会产生额外的网络费用。\n#### 2.主流地图运营商没有覆盖的室内空间定位\n\n地图运营商的室内WiFi定位往往局限于热门地点，例如大型商场。对于诸如学生宿舍楼层内空间等非热门地点，运营商往往无法提供较为准确的定位。而利用WiFiLocation，用户可以自行构建室内定位坐标，实现室内定位。\n\n对于以下使用需求，作者强烈不建议使用WifiLocation：\n#### 1.高精度定位\n\n由于WiFiLocation是基于K-NN算法的定位系统，定位算法和条件判断较为简单，所以该系统的定位精度较差。对精度要求较高的开发者，作者建议使用主流网络运营商提供的GPS或蜂窝网络定位方案。\n\n#### 2.大量地点的识别定位\n\nWiFiLocation是完全本地化的定位系统，因而它的可存储地点信息数目受限于Sqlite数据库的性能以及手机的内存，其定位速度也受限于地点数目及手机性能。当数据库储存的地点信息过多时，WiFiLocation单次定位的所需时间会过长，“实时”定位的效果不再显现，整个系统的运行效益将不复存在。对于需要存储大量地点的开发者，作者同样不建议使用本系统。\n\n#### 3.高频定位\n在前期测试当中，作者发现，WiFiLocation单次定位运算所需时间，普遍不超过500毫秒，但考虑到测试集地点较少，遂估计在录入地点较多的情况下，单次定位运算时间可能会接近1秒。若开发者以低于1秒的间隔频繁调用定位方法，很可能导致系统崩溃。所以对于需要以极高频率获取定位的开发者，作者建议使用其他的定位方案。\n\n下面介绍WiFiLocation的安装和使用。\n\n## 下载\n* **[WiFiLocation.jar](https://raw.githubusercontent.com/mozhiingithub/WiFiLocation/master/WiFiLocation.jar)**\n\n## 安装\n#### 1.加载jar包\n\n打开Android Studio，创建项目，将下载好的WiFiLocation.jar复制到libs文件夹当中，并右键点击“Add As Library”。\n\n#### 2.添加权限\n\n在 **AndroidManifest.xml** 文件中添加以下代码：\n\n``` xml\n    \u003cuses-permission android:name=\"android.permission.INTERNET\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" /\u003e\n```\n**注意：自 Android 6.0后，系统在获取WiFi扫描结果前需保证手机GPS定位选项开启，且程序中关于定位的权限必须为“允许”，否则系统每次获取扫描结果将为空值。开发者需自行设计定位选项状态及权限获取状态检查机制。**\n\n#### 3.添加LitePal依赖\n\n打开 **build.gradle** 文件并添加以下依赖：\n``` groovy\ndependencies {\n    compile 'org.litepal.android:core:1.6.0'\n}\n```\n\n#### 4.配置litepal.xml\n\n在main文件夹中，新建 **assets** 文件夹，并新建 **litepal.xml** 文件，用以下代码进行覆盖：\n``` xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003clitepal\u003e\n    \u003cdbname value=\"location\" /\u003e\n    \u003cversion value=\"6\" /\u003e\n    \u003clist\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.WiFiScanResult\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.Component\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.WiFiVector\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.Location\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.CddVtr\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.CddMac\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.Leftmix\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.Rightmix\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.ReferVector\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.ScanVector\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.PredictResult\"\u003e\u003c/mapping\u003e\n        \u003cmapping class=\"mozhi.wifilocation.Database.PredictResult2\"\u003e\u003c/mapping\u003e\n\n\n    \u003c/list\u003e\n\u003c/litepal\u003e\n```\n#### 5.初始化定位对象WiFiLocationClient\n\n在onCreate方法中对定位对象WifiLocationClient进行初始化：\n\n```java\npublic class Application {\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        WiFiLocationClient wiFiLocationClient=new WiFiLocationClient(this);\n    }\n    ...\n}\n```\n\n至此，我们完成了WiFiLocation的安装操作。\n\n## 使用\n\n### 录入、更新、删除相关方法\n\n#### 1.获取和设定K值\n\nWiFiLocation是基于K-NN算法的定位系统，我们可以通过 **getK()** 获取系统当前K值，或 **setK(int k)** 以设定系统的K值。系统默认的K值为10。\n\n```java\n        int k_get=wiFiLocationClient.getK();\n        int k_set=7;\n        wiFiLocationClient.setK(k_set);\n```\n\n#### 2.获取和设定N值\n\n在WiFiLocation当中，调用一次涉及WiFi指纹录入操作的API，系统会自动录入N次，我们可以通过 **getN()** 获取系统当前N值，或 **setN(int n)** 以设定系统的N值。系统默认的N值为10。\n\n```java\n        int n_get=wiFiLocationClient.getN();\n        int n_set=1;\n        wiFiLocationClient.setN(n_set);\n```\n\n#### 3.获取和设定Delay值\n\n在WiFiLocation当中，调用一次涉及WiFi指纹录入操作的API，系统录入N次指纹的间隔为Delay毫秒，我们可以通过 **getDelay()** 获取系统当前Delay值，或 **setDelay(int delay)** 以设定系统的Delay值。系统默认的Delay值为1000。虽无强制规定，但作者**强烈不建议**将Delay设定为低于1000的值。\n\n```java\n        int delay_get=wiFiLocationClient.Delay();\n        int delay_set=3000;\n        wiFiLocationClient.setDelay(delay_set);\n```\n\n#### 4.创建新地点\n\n我们可以使用 **Create(String location_name)** 方法创建新地点。该方法首先会判断输入的地点名在数据库中是否存在。若存在，则系统抛出 **WiFiLocationException**异常 ；若不存在，则系统创建以 **location_name** 为名的新地点，并以Delay毫秒为间隔，扫描并录入N次WiFi指纹信息。\n\n**Create(String location_name)** 还有两个重载形式，分别为：\n * **Create(String location_name,int delay)** \n * **Create(String location_name,int delay,int n)** \n \n 这两个重载形式可以修改设定本次创建操作的Delay值或N值，但不会修改系统的Delay值或N值。\n\n由于**Create(String location_name)** 是耗时操作，所以开发者不应在主线程当中使用本方法。\n```java\nString name=\"name_of_place\";\ntry {\n        wiFiLocationClient.Create(name);\n        } catch (WiFiLocationException e) {\n        e.printStackTrace();\n        } catch (InterruptedException e) {\n        e.printStackTrace();\n        }\n\n```\n\n#### 5.更新地点指纹信息\n\n我们可以使用 **Update(String location_name)** 方法来更新某地点的WiFi指纹信息。该方法首先会判断输入的地点名在数据库中是否存在。若不存在，则系统抛出 **WiFiLocationException**异常 ；若存在，则系统将为以**location_name** 为名的地点，以Delay毫秒为间隔，扫描并录入N次WiFi指纹信息。\n\n**Update(String location_name)** 还有两个重载形式，分别为：\n * **Update(String location_name,int delay)** \n * **Update(String location_name,int delay,int n)** \n \n 这两个重载形式可以修改设定本次更新操作的Delay值或N值，但不会修改系统的Delay值或N值。\n\n由于**Update(String location_name)** 是耗时操作，所以开发者不应在主线程当中使用本方法。\n```java\nString name=\"name_of_place\";\ntry {\n        wiFiLocationClient.Update(name);\n        } catch (WiFiLocationException e) {\n        e.printStackTrace();\n        } catch (InterruptedException e) {\n        e.printStackTrace();\n        }\n\n```\n\n#### 6.重置地点指纹信息\n\n我们可以使用 **Reset(String location_name)** 方法来重置某地点的WiFi指纹信息。该方法首先会判断输入的地点名在数据库中是否存在。若不存在，则系统抛出 **WiFiLocationException**异常 ；若存在，则系统将清除以**location_name** 为名的地点的所有WiFi指纹信息，然后以Delay毫秒为间隔，重新扫描并录入N次WiFi指纹信息。\n\n**Reset(String location_name)** 还有两个重载形式，分别为：\n * **Reset(String location_name,int delay)** \n * **Reset(String location_name,int delay,int n)** \n \n 这两个重载形式可以修改设定本次重置操作的Delay值或N值，但不会修改系统的Delay值或N值。\n\n由于**Reset(String location_name)** 是耗时操作，所以开发者不应在主线程当中使用本方法。\n```java\nString name=\"name_of_place\";\ntry {\n        wiFiLocationClient.Reset(name);\n        } catch (WiFiLocationException e) {\n        e.printStackTrace();\n        } catch (InterruptedException e) {\n        e.printStackTrace();\n        }\n\n```\n\n#### 7.删除地点\n\n我们可以使用 **Clear(String location_name)** 方法来删除某地点。该方法首先会判断输入的地点名在数据库中是否存在。若不存在，则系统抛出 **WiFiLocationException**异常 ；若存在，则系统将清除以**location_name** 为名的地点及其所有WiFi指纹信息。\n\n```java\nString name=\"name_of_place\";\ntry {\n        wiFiLocationClient.Clear(name);\n        } catch (WiFiLocationException e) {\n        e.printStackTrace();\n        } catch (InterruptedException e) {\n        e.printStackTrace();\n        }\n\n```\n\n#### 8.删除所有地点\n\n我们可以使用 **ClearAll()** 来删除数据库中的所有地点及WiFi指纹信息。\n```java\nwiFiLocationClient.ClearAll();\n```\n#### 9.获取所有地点\n\n我们可以使用 **getLocation()** 来获取数据库中的所有地点。\n```java\nList\u003cLocation\u003e locations=wifiLocationClient.getLocation();\n```\n\n### 定位相关方法\n\n#### 1.获取和设定M值\nWiFiLocation是基于K-NN算法的定位系统，但考虑到定位算法本身较为简单，极端情况下，会出现当前位置离系统预测地点较远时，系统仍依据K-NN算法判定当前位置已接近预测低点，导致较大误差的出现，遂引入曼哈顿距离阈值的机制，对K-NN的定位判断进行距离层面的修正，从而提高定位准确度。在本SDK中，曼哈顿距离阈值记为 **M** 值。\n\n我们可以通过 **getM()** 获取系统当前M值，或 **setM(int m)** 以设定系统的M值。系统默认的M值为10。\n\n```java\n        int m_get=wiFiLocationClient.getM();\n        int m_set=15;\n        wiFiLocationClient.setM(m_set);\n```\n\n\n\n#### 2.获取目标地点定位排名\n\nWiFiLocation是基于K-NN算法的定位系统，单次扫描后，计算库中所有可能属于当前位置的WiFi指纹信息与当前位置的WiFi指纹信息的曼哈顿距离，由小到大进行排序，获取前K个匹配度最高的WiFi指纹信息，再对这K个以地点作阈值为M的筛选，剔除超过M值的WiFi指纹信息，再以地址为单位进行count运算，得到候选地点各自的指纹信息数，由大到小进行排序，最终获得一个排名。依据K-NN算法，我们可以认定，排名第一的地点，最有可能是当前地点，而排名靠后的地点，亦可能在当前地点的附近。\n\n我们可以使用 **LocationRank(String location_name)** 方法以获取以**location_name** 为名的地点在本次定位结果中的排名，返回值类型为int。\n\n该方法首先会判断输入的地点名在数据库中是否存在。若不存在，则系统抛出 **WiFiLocationException**异常 ；若存在，则系统将返回排名值。若本次定位结果中没有目标地点，系统将返回 **0** 值。\n\n**LocationRank(String location_name)** 还有两个重载形式：\n * **LocationRank(String location_name,int k)** \n * **LocationRank(String location_name,int k,int m)** \n \n 这个重载形式可以修改设定本次定位操作的K值或M值，但不会修改系统的K值或M值。\n\n 值得注意的是，系统没有提供单次仅修改M值的重载形式，所以开发者可选择调用 **getM()** 和 **setM(int m)** 方法来实现该效果。\n \n 由于**LocationRank(String location_name)** 是耗时操作，所以开发者不应在主线程当中使用本方法。\n```java\nString name=\"name_of_place\";\ntry {\n        int rank=wiFiLocationClient.LocationRank(name);\n        } catch (WiFiLocationException e) {\n        e.printStackTrace();\n        } catch (InterruptedException e) {\n        e.printStackTrace();\n        }\n\n```\n#### 3.获取目标地点定位排名列表\n\n我们可以使用 **getLocateResult()** 方法来获取定位算法生成的排名列表。其定位过程与 **LocationRank(String location_name)** 方法相同。\n\n **getLocateResult()** 还有两个重载形式：\n *  **getLocateResult(int k)**\n *  **getLocateResult(int k,int m)** \n\n 这个重载形式可以修改设定本次定位操作的K值或M值，但不会修改系统的K值或M值。\n\n 值得注意的是，系统没有提供单次仅修改M值的重载形式，所以开发者可选择调用 **getM()** 和 **setM(int m)** 方法来实现该效果。\n\n由于 **getLocateResult()**  是耗时操作，所以开发者不应在主线程当中使用本方法。\n```java\nList\u003cPredictResult2\u003e result2s=wiFiLocationClient.getLocateResult();\n```\n## 更新\n\n#### 17.9.25\n* 修改了系统的定位算法，引入曼哈顿距离阈值机制\n* 新增 **getM()** 和 **setM(int m)** 方法\n* 修改 **LocationRank(String location_name)** 和 **getLocateResult()** 方法，并增加了重载形式\n\n#### 17.9.22\n* 修复 **Create(String location_name, int delay, int n)** 漏洞\n\n#### 17.9.21\n* 添加 **getLocation()** 方法\n* 添加 **getLocateResult()** 方法\n\n## 联系作者\n\n由于时间久远，且立项时未撰写相关文档，故难以回答诸多实现细节（说人话：写完太久了，我自己都看不懂了。。。），遂就该项目不再提供答疑，非常抱歉。2020.3.2\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmozhiingithub%2Fwifilocation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmozhiingithub%2Fwifilocation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmozhiingithub%2Fwifilocation/lists"}