電話の位置を特定します... GPSなし

ハブ「Java for MEの開発」に目を向けると、 Spb Transport J2MEのトピックに出会いました。著者はマップサービスを使用し、TODOの1つはGPSサポートです(使いやすさを向上させるため)。 問題は、GPS受信機を内蔵した電話機が比較的少ないことです。 この投稿がそのトピックの著者だけでなく、誰か他の人にも役立つことを願っています。 それでは始めましょう。



ユーザー(好きなように電話)の場所を決定するには、いくつかの方法を使用できます。

-GPSによる。 この方法は最も正確です。 欠点の中でも、比較的長いスタートは多くのエネルギーを消費しますが、統合された受信機を備えたデバイスはそれほど多くありません。

-オペレーターの塔の上。 中程度の精度。 彼は少しエネルギーを食べる。 マイナス面:すべての電話でデータが利用できるわけではありません。

-IPによる。 あまり正確ではありません。 実際、これは最大のマイナスです。

-オペレーターCBメッセージによる



そのため、場所の決定には多少許容できる精度が必要です(市の場合はそれぞれ約150-300メートル(これは徒歩で1.5-2分)、市外では2-5 km以上、幸運なことに)ただし、できるだけ多くのデバイスをカバーする必要があり、座標をすばやく更新することをお勧めします。

最も適切なのは、携帯電話会社のデータによる位置です。



サービス:
ネットワークデータを変換して座標を取得するには、携帯電話の塔のデータベースが必要です。 ネットワークには多くのリソースがあります。実績のあるGoogleMaps、Yandex.Locator、location-api.com、opencellid.orgを使用しました(精度と信頼性を高めるために、すべてを一度に使用しています)。 さらに、ボーナスとして、Yandex APIには、信号強度に基づいて位置を決定する方法がありますが、それについては後で詳しく説明します。

各サービスには、十分に文書化されたAPIがあります(GoogleMapsを除く)。 APIで受け入れられるパラメーター:MCC(国コード)、MNC(ネットワークオペレーターコード)、LAC(セルコード)、CellID(タワー識別子)。

APIは、このデータセットの座標を返します。



データ:
上記のデータを取得するのは簡単な作業ではありません。各メーカーが自分の自転車を発明することは名誉な問題だと考えているためです。 その結果、各ブランドにはSystem.getProperty(キー)を呼び出すための独自のキーセットがありますが、これは簡単に見つけることはできません。

他にも多くの不快な瞬間があります。 たとえば、シーメンスでは、ファームウェアにパッチを適用しないとネットワークデータを取得できません。 SonyEricssonは、データをHEX表現で返します。 ノキアは、認定されていない(つまり、ほとんどすべての)ミッドレットにLACを提供することを拒否しています。



解決策:
既知のキーを反復処理し、これらのキーからネットワーク情報を取得するクラスを作成しました。 次に、キーがサービスAPIに送信され、座標が取得され、平均値が推定されました。これが最も妥当であると考えられます(1年間の使用では、非常に大きなエラーのケースは思い出せません)。 電話で信号強度を取得できる場合、Yandexボーナスを使用します:信号強度とWITHOUTなしの座標を取得し、これらの値のデルタを取得し、APIからのすべての結果に適用し、平均結果を表示します。 奇妙なことに、最後の決定は両刃の剣であることが判明しました。 信号が均一に減衰すると、通常の方法と比較して精度が2倍になりますが、信号が不均一に分布する密集した市街地または丘陵地の場合、この場合、精度は非常に大きく低下します。



その結果、Siemens、SonyEricsson、Samsung(s5230など)、Huaweiなどの電話で位置を特定することができます。 座標とアドレスの読み込み時間は約10〜15秒です。

デモの例(アドインクラスLocationを使用します。このクラスでは、座標が決定され、アドレスがロードされます)
import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Form; import javax.microedition.midlet.MIDlet; import loc.*; public class HelloWorld extends MIDlet implements Runnable { Display display; Form form; public void startApp() { display = Display.getDisplay(this); form = new Form("NetMonitor"); display.setCurrent(form); new Thread(this).start(); } public void run() { //    if (!Location.reallyNull(Location.lac)) { //   Location.getData(); //  Location.getCoordinates(); //      if (!Location.reallyNull(SystemUtil.signal())) { form.append((": ") + "\n : " + String.valueOf(Location.mcc) + " \n : " + String.valueOf(Location.mnc) + " \n : " + String.valueOf(Location.lac) + " \n C: " + String.valueOf(Location.cid) + " \n : " + SystemUtil.signal() + " \n"); } // else { form.append(": " + "\n : " + String.valueOf(Location.mcc) + " \n : " + String.valueOf(Location.mnc) + " \n : " + String.valueOf(Location.lac) + " \n : " + String.valueOf(Location.cid) + " \n"); } } //    String txt = SystemUtil.nativeDigitSupport(); if (!Location.reallyNull(txt)) { form.append(txt + "\n"); } txt = SystemUtil.operatorName(); if (!Location.reallyNull(txt)) { form.append(txt + "\n"); } txt = SystemUtil.serviceProvider(); if (!Location.reallyNull(txt)) { form.append(txt + "\n"); } txt = SystemUtil.traffic(); if (!Location.reallyNull(txt)) { form.append(txt + "\n"); } txt = SystemUtil.gid1(); if (!Location.reallyNull(txt)) { form.append(txt + "\n"); } txt = SystemUtil.gid2(); if (!Location.reallyNull(txt)) { form.append(txt + "\n"); } // form.append(": ".concat(String.valueOf(Location.getStreet().concat(" \n")))); form.append(": ".concat(String.valueOf(Location.getCity().trim().concat(" \n")))); form.append(": ".concat(String.valueOf(Location.getArea().concat(" \n")))); form.append(": ".concat(String.valueOf(Location.getCountry().concat(" \n")))); form.append(": ".concat(String.valueOf(Location.getLongitude().concat(" \n")))); form.append(": ".concat(String.valueOf(Location.getLatitude().concat(" \n")))); form.append("  ..: ".concat(String.valueOf(Location.getElevation().concat("  \n")))); //   String sens = System.getProperty("microedition.sensor.version"); if (sens != null && sens.length() != 0 && !sens.equals("null")) { sens = SensorApi.getSensor(3); if (sens != null && sens.length() != 0 && !sens.equals("null") && !sens.equals("0")) { form.append("  : " + String.valueOf(sens) + " \n"); } } } public void pauseApp() { } public void destroyApp(boolean flag) { } }
      
      









さて、デモ付きのソースコード

goo.gl/lPkON



All Articles