1

サービスによって開始されたスレッドから位置情報の更新をリクエストする際に問題があります。

私のアプリケーションは、バックグラウンド サービスから (UI スレッドなしで) 位置情報の更新を取得する必要があります。アプリケーションの構造について説明します。

  1. Boot Receiver によって開始されるサービスがあります。
  2. サービスではonStartCommand()、スケジューラ スレッドを開始します。
  3. スケジューラ スレッドは、場所の更新を要求します。

問題は、スケジューラが呼び出すとき です。他の人にも同様の問題を見たが、解決策が見つからないlocationMgr.requestLocationUpdates() と言われています。Can't create handler inside thread that has not called Looper.prepare()サービスから直接呼び出して問題なく位置情報の更新を取得できると聞きましたが、サービスをスリープ状態にする方法 (スケジューラ スレッドなど) が見つからないため、別のスレッドが必要だと思います。

なぜこれが起こっているのか説明してください。Androidは場所をリクエストするためにUIスレッドを必要としますか? アプリケーション構造を変更することによる解決策はありますか?

4

4 に答える 4

2

LooperMessage's / Runnables(そのスレッドにを介して投稿されたもの)のスレッドキューをポーリングし続けるものHandlerです。UIスレッドにはデフォルトで1つあります。カスタムスレッドの場合、スレッドを開始する前に設定する必要があります。

例で述べたように:

スレッドのメッセージループを実行するために使用されるクラス。デフォルトでは、スレッドにはメッセージループが関連付けられていません。作成するには、ループを実行するスレッドでprepare()を呼び出してから、loop()を呼び出して、ループが停止するまでメッセージを処理させます。

ここで、RequestLocationUpdates()スレッドに更新を配信するメカニズムが必要ですが、スレッドにはLooperポーリングがありません。

RequestLocationUpdates()移動とそれに対応removeUpdates()するサービススレッドを検討してください。ほとんどの場合、サービスが開始および停止する場所です。

于 2013-02-22T12:25:19.250 に答える
1

発生する理由は次のとおりです。getLooperはコンテキストのUIに接続されていますが、サービスはackgroundプロセスであり、UIに直接接続されていません。だからあなたの取得エラー。

問題の解決策:

1)ロケーションクラスを他のパッケージに配置します。2)そのパッケージ名をインポートします。3)パッケージ内で1つのコールバックインターフェイスを使用します。4)サービスコンポーネントでインターフェイスインスタンスを使用します。5)動作します!!

于 2013-02-22T12:19:31.677 に答える
1

私はこれを使用しましたが、正常に動作します: To get location in service

ここのサービスクラス:

public class MyService extends Service {

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();

    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        super.onStart(intent, startId);

        // start location manager
        LocationDetermined objLocationDetemined = new LocationDetermined(this);
        objLocationDetemined.getlocation(this);
        objLocationDetemined.getRecentKnownLocation(this);

    }

ここのロケーションクラス:

public class LocationDetermined implements OnInitListener {

    String TAG = "LocationDeterminedClass";
private static LocationManager locationManager;
double Lat = 0.0;
double Long = 0.0;
GeoPoint geoPoint;
private Toast mToast;
Context appContext;
static MyLocationListener locationListener;

    public LocationDetermined(Context context) {
        this.appContext = context;

    }

    public MyLocationListener getlocation(Context appContext) {

        locationManager = (LocationManager) appContext
                .getSystemService(Context.LOCATION_SERVICE);
        locationListener = new MyLocationListener();
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
        String provider = locationManager.getBestProvider(criteria, true);

        Log.d(TAG, "------provider------" + provider);


        if (provider != null && locationManager.isProviderEnabled(provider)) {
            locationManager.requestLocationUpdates(provider, 0, 0,
                    locationListener);
        } else {
            Toast.makeText(appContext, "No provider available to get loctaion",
                    2000).show();
        }
        return locationListener;
    }



    private class MyLocationListener implements LocationListener {

        public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub

        }

        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub

        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO Auto-generated method stub

        }

        public void onLocationChanged(final Location argLocation) {
            // TODO Auto-generated method stub
            if (argLocation != null) {
                Lat = argLocation.getLatitude();
                Long = argLocation.getLongitude();

                Log.e("OnLocationChanged:", "lat:" + Lat + "  long:" + Long);

                Log.d("service gps", "lat" + argLocation.getLatitude() + "-"
                        + argLocation.getLongitude());

                Constant.mLatitude = argLocation.getLatitude();
                Constant.mLongitude = argLocation.getLongitude();               
            }
        }
    }

    public GeoPoint getRecentKnownLocation(Context appContext) {
        Location locGps = locationManager
                .getLastKnownLocation(LocationManager.GPS_PROVIDER);
        Location locNet = locationManager
                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

        Location locPassive = locationManager
                .getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
        if (locGps != null) {
            Lat = locGps.getLatitude();
            Long = locGps.getLongitude();

            Constant.mLatitude = locGps.getLatitude();
            Constant.mLongitude = locGps.getLongitude();

            geoPoint = new GeoPoint((int) (Lat * 1000000),
                    (int) (Long * 1000000));
            return geoPoint;

        } else if (locNet != null) {
            Lat = locNet.getLatitude();
            Long = locNet.getLongitude();

            Constant.mLatitude = locNet.getLatitude();
            Constant.mLongitude = locNet.getLongitude();

            geoPoint = new GeoPoint((int) (Lat * 1000000),
                    (int) (Long * 1000000));
            return geoPoint;

        }
        return geoPoint;
    }

    private void fetchedSavedLocationDetail(Context mContext) {

    }

    @Override
    public void onInit(int status) {
        // TODO Auto-generated method stub

    }

    public static void removeLocationListener() {

        locationManager.removeUpdates(locationListener);
    }

}

これらの変数を定数クラスで使用して、場所を格納しました public static double mLatitude = 0.0, mLongitude = 0.0;

サービスを開始します startService(new Intent(this, MyService.class));

于 2013-02-22T12:46:34.650 に答える
0

Handler を使用して修正しました。

  1. ハンドラを作成しました。
  2. サービスコードを入れましたhandleMessage()
  3. 必要な間隔で空のメッセージをハンドラーに送信するスレッドを作成します (while ループ)。
  4. したがって、ハンドラが空のメッセージを受け取ると、handleMessage()実際のスケジューラ ループを含むを実行します。
于 2013-02-22T13:48:33.970 に答える