2017-01-31 5 views
0

デバイスセンサーと位置情報を使用するアンドロイドアプリを作成しています。両方の情報源からのデータは、方位に関するいくつかのことを計算するために使用されます。これまでは、2つの非アクティビティクラスを作成しました.1つはセンサー管理用、もう1つはロケーション管理用です。問題は、たとえば、アクティビティやコンテキストが必要なものを使用したい場合です。たとえば、startResolutionForResult()を呼び出してダイアログを表示し、結果をonActivityResult()にチェックします。 startResolutionForResult()ダイアログを表示するにはアクティビティが必要です。 これを解決する最善の方法は何ですか?私は各非活動クラスのフィールドメンバーとしてコンテキストを使用することに決めましたが、それが最良の選択肢かどうかはわかりません。アクティビティ、コンテキストメソッド、および非アクティビティクラスのオブジェクト

更新 ここに私が喜んでいるコードの一部です。私は場所がオンになっているかどうかを確認するためcheckLocationSettings()メソッドを呼び出すonCreate()方法で

Then onResult()コールバックが発生し、場所の設定に応じて何をすべきかを判断できます。場所はオフになっているとき、それは すべてが魔法のように動作MainActivity.classの一部であるonActivityResult()

status.startResolutionForResult((Activity)getBaseContext(), REQUEST_CHECK_SETTINGS) 
ユーザーの決定の結果が利用可能である

によって呼び出されるダイアログを示しているが、私は(活動についてconcerndよ)getBaseContext()特に。

GoogleServiceLocationProvider.class

public class GoogleServiceLocationProvider extends ContextWrapper implements GoogleApiClient.ConnectionCallbacks, 
    GoogleApiClient.OnConnectionFailedListener, LocationListener, ResultCallback<LocationSettingsResult> { 

private static final int REQUEST_CHECK_SETTINGS = 3; 

private static final int UPDATE_INTERVAL = 10 * 1000; // 10 seconds 
private static final int DISPLACEMENT = 10;    // 10 meters 

private GoogleApiClient googleApiClient; 
private LocationRequest locationRequest; 

private Location lastLocation; 
private long lastTime; 

LocationFinder.LocationUpdateListener locationUpdateListener; 
private boolean isListenerRunning; 

private LocationSettingsRequest locationSettingsRequest; 

public GoogleServiceLocationProvider(Context base) { 
    super(base); 

    buildApiGoogleClient(); 
    createLocationRequest(); 
    buildLocationSettingsRequest(); 
} 

private void buildLocationSettingsRequest() { 
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); 
    builder.addLocationRequest(locationRequest); 
    locationSettingsRequest = builder.build(); 
} 

public void checkLocationSettings() { 
    if(googleApiClient != null && locationSettingsRequest != null){ 
     PendingResult<LocationSettingsResult> result = 
       LocationServices.SettingsApi.checkLocationSettings(
         googleApiClient, 
         locationSettingsRequest 
       ); 
     result.setResultCallback(this); 
    } 
} 

@Override 
public void onResult(@NonNull LocationSettingsResult locationSettingsResult) { 
    final Status status = locationSettingsResult.getStatus(); 
    switch (status.getStatusCode()) { 
     case LocationSettingsStatusCodes.SUCCESS: 
      break; 
     case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: 
      try { 
       status.startResolutionForResult((Activity)getBaseContext(), REQUEST_CHECK_SETTINGS); 
      } catch (IntentSender.SendIntentException e) { 
      } 
      break; 
     case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: 
      break; 
    } 
} 

MainActivity.class

一人ひとりのクラスにコンテキストのを渡す
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    useGoogleLocationServiceAPI(); 
} 

private void useGoogleLocationServiceAPI(){ 
    googleServiceLocationProvider = new GoogleServiceLocationProvider(this); 
    googleServiceLocationProvider.checkLocationSettings(); 
} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 

    switch(requestCode){ 

     case PLAY_SERVICES_RESOLUTION_REQUEST: 
      switch(resultCode){ 
       case RESULT_OK: 
        isGoogleLocationService = true; 
        useGoogleLocationServiceAPI(); 
        break; 
       case RESULT_CANCELED: 
        Toast.makeText(this, getString(R.string.google_location_service_missing), 
          Toast.LENGTH_SHORT).show(); 
        useAndroidLocationAPI(); 
        break; 
      } 
      break; 

     case REQUEST_CHECK_SETTINGS: 
      switch(resultCode){ 
       case RESULT_OK: 
        break; 
       case RESULT_CANCELED: 
        Toast.makeText(this, getString(R.string.location_off_message), 
          Toast.LENGTH_SHORT).show(); 
        break; 
      } 
      break; 
    } 
} 
+1

は、「コンテキスト」を関数のパラメータとして渡します。 –

+0

getApplicationContextを使用します。アプリケーションの有効範囲はgetApplicationContextです。 – AndroidBeginner

+1

@AndroidBeginnerこれはどこでも利用できません。 – AnixPasBesoin

答えて

1

更新

はあなたがcontextと仮定されているコードstatus.startResolutionForResult((Activity)getBaseContext(), /*...*/);のこのラインにより、そのあなたのコンストラクタに渡されたGoogleServiceLocationProviderは、必ずしもそうでないかもしれないActivityです。 Serviceを使用していた場合はどうなりますか?この行(Activity)getBaseContext()ClassCastExceptionです。

あなたのGoogleServiceLocationProviderはそれをすべて持っていることを確認するために、Activityが必要な場合は、その理由だけではなく、あなたのコンストラクタでContextActivityインスタンスを必要としないのですか?

private Activity activity; 
public GoogleServiceLocationProvider(Activity activity) { 
    super(activity.getContext()); 
    this. activity = activity; 
    //... 
} 

あなたはその後でので、あなたのようなonResult方法で使用します。あなたの最初の質問に答えるために今

@Override 
public void onResult(@NonNull LocationSettingsResult locationSettingsResult) { 
    //... 
    status.startResolutionForResult(this.activity, REQUEST_CHECK_SETTINGS); 
    //... 
} 

Androidの事実あなたはいつもcontextが何らかの形で提供されていますあなたのコードを実行している

それはActivityServiceApplicationBoradcastReceiverだかどうか...あなたはあなたのcontextへの直接的/間接的にアクセスすることができます。

したがって

最も簡単なまだ、より効率的かつデカップリングアプローチは、カスタムクラスへの参照としてこのcontextを渡すことです。後で使用するには、class(依存関係注入)のどこかにあるcontextへの参照を保持することができますが、leaksに注意してください。

一部コード

class MyClass { 
    //... 
    public void doSomethingWithTheContext (Context context) { 
     //... 
     context.doThis(/*...*/); 
     //... 
    } 
} 

使用FragmentからActivityから

ApplicationService ...(すべてContextを拡張)

myInstanceOfMyClass.doSomethingWithTheContext(this); 
myInstanceOfMyClass.doSomethingWithTheContext(getActivity()); 

関連質問

Using Application context everywhere?

+0

私の投稿を更新しました – sheddar

+0

@kobasek私は自分の答えを更新しました。 – AnixPasBesoin

2

は一つの選択肢です。しかし、私はこれらのクラスを疎結合にしておき、データの送受信にEventBusを使用することをお勧めします。特定のタイプのイベントに関心のあるソフトウェアコンポーネントに通知するための集中化された方法を提供します。イベントの発行者のコードとそれを受け取るコードの間に直接の結合は存在しません。適切に設計されたデカップリングされたシステムは、何かが変化した場合に備えてコンポーネント間で変更を加える必要性を減らします。

ライブラリがここにあります:EventBus

ここで同じ説明さらに簡単チュートリアルです:How to use the greenrobot EventBus library

+0

私は、 'EventBus'がデータ転送を管理する方法であることに同意します。しかし、あなたはこれがこのような疑問に対して過度のものだとは思わない?そして、そのことは、クラスが意味することを実行するために彼のクラスが 'コンテキスト'を必要としているので、あなたは 'EventBus'を使って何かを切り離していません。 – AnixPasBesoin

+0

いいえ、EventBusは、一時的な性質のため、アクティビティと通信しようとしているときの合理的な解決策です。 – EpicPandaForce

0

あなたはこのように、メソッドにContextまたはActivityオブジェクトのいずれかを渡すことができます。onActivityResult()値を取得するには

public void startResolutionForResult(Context context) { 
    contex.showYourAlert(); 
} 

、パラメータとして渡すことも、を作成することもできますあなたのActivityの中のメソッド。

関連する問題