2017-05-23 12 views
2

こんにちは私はユーザーの場所を取得するアンドロイドマップアプリケーションを作成していますが、ユーザーがマップを開いたときに場所が正確でなく、getAccuracy()が100よりも低いときにハンドラを停止する方法

私はこれを試しました。しかし、それはまだハンドラを呼び出し、TOASTSは停止しません。

private LocationManager locationManager; 

private Handler handler = new Handler(); 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_maps_page); 

locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() { 
     @Override 
     public void onLocationChanged(Location location) { 

     } 

     @Override 
     public void onStatusChanged(String provider, int status, Bundle extras) { 

     } 

     @Override 
     public void onProviderEnabled(String provider) { 
       handler.postDelayed(runnable,3000); 
     } 

     @Override 
     public void onProviderDisabled(String provider) { 

      handler.removeCallbacks(runnable); 
     } 
    }); 

     private Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 

     getCurrentLocation(); 

     Toast.makeText(mapsPage.this, "GETTING LOCATION", Toast.LENGTH_SHORT).show(); 

     handler.postDelayed(this, 3000); 
    } 
}; 

    private void getCurrentLocation() { 
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     return; 
    } 
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); 
    if (location != null) { 
     longitude = location.getLongitude(); 
     latitude = location.getLatitude(); 

     moveMap(); 

     Integer loc = Math.round(location.getAccuracy()); 
     textings.setText(Integer.toString(loc)); 

     if(loc <= 100) 
    { 
     handler.removeCallbacks(runnable); 

     Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show(); 
    } 

    } 
} 

//Function to move the map 
private void moveMap() { 

    LatLng latLng = new LatLng(latitude, longitude); 

    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); 
    mMap.animateCamera(CameraUpdateFactory.zoomTo(17)); 
    mMap.addMarker(new MarkerOptions().position(latLng).draggable(false)); 

} 

私は、ユーザーの位置を確認し、5秒ごとに実行され、getAccuracyデータが100よりも同等以下のいずれかであるとき、それは停止しますハンドラを追加しました。どうすればいい?

答えて

3

getCurrentLocationはhandler.removeCallbacks(runnable);を呼び出すことができますが、実行可能ファイルは常にhandler.postDelayed(this, 3000);を呼び出します。

これを修正するには、Runnableが再度ポストする必要があるかどうかを確認するための条件がなければなりません。

ソリューションはgetCurrentLocationは、それが(十分に)成功した​​かどうかを示すブール値を返す作るために次のようになります。

private boolean getCurrentLocation() { 
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && 
      ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     return false; 
    } 
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); 
    if (location != null) { 
     longitude = location.getLongitude(); 
     latitude = location.getLatitude(); 

     moveMap(); 

     Integer loc = Math.round(location.getAccuracy()); 
     textings.setText(Integer.toString(loc)); 

     if(loc <= 100) { 
      handler.removeCallbacks(runnable); 
      Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show(); 
      return true; 
     } 
    } 
    return false; 
} 

次に、あなたのRunnableをチェックして、あなたが別の実行を持っている必要がある場合:

@Override 
public void run() { 
    if(!getCurrentLocation()) { 
     handler.postDelayed(this, 3000); 
    } 
} 

これらのことはすべて、あなたのLocationListenerのonLocationChanged内のLocationをチェックして何かその場所が十分正確であれば。その後、Runnableはまったく必要ありません。

+0

こんにちは、私はこれですべてのナイターを引っ張って、私は答えを見つけました。私はtimerTaskを使用し、スナックバーでトーストを置き換え、それは本当にうまくいった。私はあなたのコードを試して、それは動作し、あなたはupvoteと受け入れられた答えに値する。助けと説明のために再びありがとう! :D –

+0

しかし、私は先生に尋ねるかもしれません、ユーザーの位置を効率的に特定するための私のコードやアプローチですか、それとも他の方法を検討する必要がありますか? –

2

RobCoの回答は、あなたの質問に直接答えるだけでなく、さらに重要な洞察を提供する(つまり、実際にはRunnableがまったく必要ない)ため、正しい答えとして受け入れるべきです。

しかし、私はRobCoのアプローチがどのように見えるか不思議でした。そのため、可能な実装を1つ作成しました。

Runnableを避け、Googleのコールバックに頼ると、新しいロケーションプロバイダAPI(LocatonServices.FusedLocationApi)のみを使用することができなくなることが判明しました。古いLocationManager APIは削除することができます。

場合/とき、(代わりに、クライアントからの定期的なポーリングを使用しての)場所の変更ので、この実装では、私はGoogleの位置情報サービスのトリガーのコールバックを聞かせて:

public class MainActivity extends AppCompatActivity implements 
     ActivityCompat.OnRequestPermissionsResultCallback, GoogleApiClient.OnConnectionFailedListener, 
     GoogleApiClient.ConnectionCallbacks, 
     com.google.android.gms.location.LocationListener { 

    private static final String TAG = MainActivity.class.getSimpleName(); 

    private static final int PERMISSION_REQUEST_CODE = 10001; 
    public static final int LOCATION_UPDATE_INTERVAL = 5000; // milliseconds 
    private GoogleApiClient googleApiClient; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     googleApiClient = new GoogleApiClient.Builder(this, this, this) 
       .enableAutoManage(this, this) 
       .addApi(LocationServices.API) 
       .build(); 

     googleApiClient.connect(); 
    } 

    private void requestPermission() { 
     ActivityCompat.requestPermissions(this, 
       new String[]{ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_CODE); 
    } 

    private void initLocationServices() { 
     try { 
      // make initial, synchronous request for current location 
      Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); 
      if (location != null) { 
       moveMap(location); 
      } 

      // request future location updates which will come in as callbacks later, when available 
      LocationRequest locationRequest = new LocationRequest(); 
      locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
      locationRequest.setInterval(LOCATION_UPDATE_INTERVAL); 
      LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this); 
     } catch (SecurityException se) { 
      Log.w(TAG, "App does not have sufficient permission to request location. " + 
        "Requesting permission now..."); 
      requestPermission(); 
     } 
    } 

    private void moveMap(Location location) { 
     Log.v(TAG, "moveMap"); 

     // TODO: actual map moving code goes here 
    } 

    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 
     Log.e(TAG, "Connection failed:" + connectionResult.getErrorMessage()); 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
     if (requestCode == PERMISSION_REQUEST_CODE && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) { 
      Log.v(TAG, "User granted permission. Will request current location."); 
      initLocationServices(); 
     } else { 
      Log.w(TAG, "User did not grant permission. Cannot request location. Cannot proceed."); 
     } 
    } 

    @Override 
    public void onLocationChanged(Location newLocation) { 
     Log.v(TAG, "onLocationChanged:" + newLocation.toString()); 
     moveMap(newLocation); 
    } 

    @Override 
    public void onConnected(@Nullable Bundle bundle) { 
     if ((ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED) 
       && (ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED)) { 
      initLocationServices(); 
     } else { 
      Log.w(TAG, "onCreate: requesting sufficient permission from user"); 
      requestPermission(); 
     } 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Log.v(TAG, "onConnectionSuspended"); 
    } 
} 

この特定の実装の欠点がありますMainActivityはいくつかのインターフェースを実装しており、いくつかの混乱を招いています(これらのメソッドは何をここでやっていますか?など)

Dunno。多分それは有用です。いずれにしても、あなたのアプリには幸運があります。

+0

こんにちは、私はすべてのnighterを引っ張ってきました。私は自分の解決策を見つけました。今はタイマータスクを使用しています。しかし、助けと説明の先生のために、あなたは価値があり、upvoteに値する。助けてくれてありがとう! –

+0

しかし、私はあなたのコードやアプローチが効率的にユーザーの位置を突き止めるためのアプローチですか、あなたのアプローチはより効率的ですか? –

+1

あなたが好きな解決策を見つけたらおめでとう。また、賛成票をいただき、ありがとうございました。どのアプローチが最も効率的かはわかりません。私のテストアプリでは、タブレットが机の上に座っていても、GoogleのLocationServices.FusedLocationApiは2〜5秒ごとに自分のアプリを更新しています。したがって、かなりの数のコールバックが生成されています。 5秒ごとに場所を尋ねるTimerTaskと似ていると思います。さらに、FWIWでは、ポーリングのアプローチを実装していた場合、ユーザーがアプリをバックグラウンドに入れて再開するときに、問題やメモリリークを探します。 –

関連する問題