2016-06-28 13 views
1

更新日 - 私の放送のアイデアを表示するためのコードを編集しました。メソッドを使用すると、!!! FAILED BINDER TRANSACTION !!!トーストで表示される位置データはありません。複数のアクティビティにわたる位置情報サービス

グーグルが融合した位置情報サービスをアクティビティから分離するためのエレガントな方法があるのだろうかと思っていました。私の警告クラスは現在位置情報サービスを実装していますが、写真を撮る別のアクティビティがあります。写真が撮られるとき、私は場所を画像に関連づけたいと思う。私の現在のアイデアは、私のBluetooth受信機を私のBluetooth警告クラスで使用して、私のカメラが送信した放送を聞いて、それを場所に関連付けることです。私はそれが機能を非常によく分離していないので、いくつかの提案やパターンを期待していたので、アイデアのファンではありません。以下のクラスのコード。

CAMERA CLASS

import android.content.Intent; 
import android.content.pm.PackageManager; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.net.Uri; 
import android.os.Environment; 
import android.provider.MediaStore; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.widget.ImageView; 
import android.widget.Toast; 

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.IOException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

public class CameraOperations extends AppCompatActivity { 
    public final static String ACTION_PICTURE_RECEIVED = "ACTION_PICTURE_RECEIVED"; 
    public final static String TRANSFER_DATA = "bitmap"; 
    ImageView mImageView; 
    String photoPath; 
    int REQUEST_IMAGE_CAPTURE = 1; 
    File photoFile = null; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.camera_view); 
     mImageView = (ImageView) findViewById(R.id.imageView); 

     if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { 
      Toast.makeText(CameraOperations.this, "No Camera", Toast.LENGTH_SHORT).show(); 
     } else { 
      dispatchTakePictureIntent(); 
     } 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK){ 
      if(data == null){ 
       Toast.makeText(this, "Data is null", Toast.LENGTH_SHORT); 
       Bitmap pictureMap = BitmapFactory.decodeFile(photoFile.getAbsolutePath()); 
       mImageView.setImageBitmap(pictureMap); 
       broadcastUpdate(ACTION_PICTURE_RECEIVED, pictureMap); 
      }else { 
       Toast.makeText(this, "Error Occurred", Toast.LENGTH_SHORT).show(); 
      } 
     } 
    } 

    private void broadcastUpdate(final String action, Bitmap picture) { 
     ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
     picture.compress(Bitmap.CompressFormat.JPEG, 100, stream); 
     byte[] bytes = stream.toByteArray(); 

     Intent intent = new Intent(action); 
     intent.putExtra(TRANSFER_DATA, bytes); 
     sendBroadcast(intent); 

     intent = new Intent(CameraOperations.this, Warning.class); 
     startActivity(intent); 
     finish(); 
    } 

    private File createImageFile() throws IOException { 
     String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
     String imageFileName = "JPEG_" + timeStamp + "_"; 
     File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); 
     File image = File.createTempFile(imageFileName, ".jpg", storageDir); 

     photoPath = "file:" + image.getAbsolutePath(); 
     return image; 
    } 

    private void dispatchTakePictureIntent() { 
     Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
     try{ 
      photoFile = createImageFile(); 
     }catch(IOException e){ 
      e.printStackTrace(); 
     } 

     if(photoFile != null){ 
      Uri photoUri = Uri.fromFile(photoFile); 
      takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); 
     } 
     startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); 
    } 
} 

BLUETOOTH警告クラス

import android.Manifest; 
import android.bluetooth.BluetoothGattCharacteristic; 
import android.bluetooth.BluetoothGattService; 
import android.content.BroadcastReceiver; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.content.ServiceConnection; 
import android.content.pm.PackageManager; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.location.Location; 
import android.os.Build; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.support.v4.app.ActivityCompat; 
import android.support.v7.app.AlertDialog; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.Toolbar; 
import android.util.Log; 
import android.view.KeyEvent; 
import android.view.Menu; 
import android.view.MenuInflater; 
import android.view.MenuItem; 
import android.widget.Toast; 

import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.GoogleApiAvailability; 
import com.google.android.gms.common.api.GoogleApiClient; 
import com.google.android.gms.location.LocationRequest; 
import com.google.android.gms.location.LocationServices; 

public class Warning extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { 
    private final static String TAG = Warning.class.getSimpleName(); 
    private String mDeviceAddress; 
    private HandleConnectionService mBluetoothLeService; 
    private boolean quitService; 
    private final int PLAY_SERVICES_REQUEST_TIME = 1000; 
    private Location mLastLocation; 
    private GoogleApiClient mGoogleClient; 
    private boolean requestingLocationUpdates = false; 
    private LocationRequest locationRequest; 

    private int UPDATE_INTERVAL = 10000; // 10 seconds 
    private int FASTEST_INTERVAL = 5000; // 5 seconds 
    private int DISTANCEMOVED = 10; //In meters 


    private final ServiceConnection mServiceConnection = new ServiceConnection() { 
     @Override 
     public void onServiceConnected(ComponentName componentName, IBinder service) { 
      mBluetoothLeService = ((HandleConnectionService.LocalBinder) service).getService(); 
      if (!mBluetoothLeService.initialize()) { 
       Log.e(TAG, "Unable to initialize Bluetooth"); 
       finish(); 
      } 
      mBluetoothLeService.connect(mDeviceAddress); 
     } 

     @Override 
     public void onServiceDisconnected(ComponentName componentName) { 
      mBluetoothLeService = null; 
     } 
    }; 

    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      final String action = intent.getAction(); 

      if (HandleConnectionService.ACTION_GATT_DISCONNECTED.equals(action)) { 
       if (!quitService) { 
        mBluetoothLeService.connect(mDeviceAddress); 
        Log.w(TAG, "Attempting to reconnect"); 
       } 
       Log.w(TAG, "Disconnected, activity closing"); 
      } else if (HandleConnectionService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { 
       getGattService(mBluetoothLeService.getSupportedGattService()); 
      } else if (HandleConnectionService.ACTION_DATA_AVAILABLE.equals(action)) { 
       checkWarning(intent.getByteArrayExtra(HandleConnectionService.EXTRA_DATA)); 
      }else if(CameraOperations.ACTION_PICTURE_RECEIVED.equals(action)){ 
       byte[] bytes = intent.getByteArrayExtra("bitmap"); 
       Bitmap picture = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 
       findLocation(); 
      } 
     } 
    }; 

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

     Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar); 
     setSupportActionBar(myToolbar); 

     if (checkGoogleServices()) { 
      buildGoogleApiClient(); 
     } 

     quitService = false; 
     Intent intent = getIntent(); 
     mDeviceAddress = intent.getStringExtra(Device.EXTRA_DEVICE_ADDRESS); 

     Intent gattServiceIntent = new Intent(this, HandleConnectionService.class); 
     bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     MenuInflater inflater = getMenuInflater(); 
     inflater.inflate(R.menu.mainmenu, menu); 
     MenuItem connect = menu.findItem(R.id.connect); 
     connect.setVisible(false); 
     MenuItem disconnect = menu.findItem(R.id.disconnect); 
     disconnect.setVisible(true); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     Intent intent; 
     switch (item.getItemId()) { 
      case R.id.home: 
       new AlertDialog.Builder(this) 
         .setIcon(android.R.drawable.ic_dialog_alert) 
         .setTitle("Return Home") 
         .setMessage("Returning home will disconnect you, continue?") 
         .setPositiveButton("Yes", new DialogInterface.OnClickListener() { 
          @Override 
          public void onClick(DialogInterface dialog, int which) { 
           quitService = true; 
           mBluetoothLeService.disconnect(); 
           mBluetoothLeService.close(); 

           Intent intent = new Intent(Warning.this, Main.class); 
           startActivity(intent); 
          } 
         }) 
         .setNegativeButton("No", null) 
         .show(); 

       return true; 
      case R.id.connect: 
       Toast.makeText(this, "Connect Pressed", Toast.LENGTH_SHORT).show(); 
       return true; 

      case R.id.disconnect: 
       disconnectOperation(); 
       intent = new Intent(Warning.this, Main.class); 
       intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
       startActivity(intent); 
       return true; 

      case R.id.profiles: 
       Toast.makeText(this, "Profiles Pressed", Toast.LENGTH_SHORT).show(); 
       return true; 


      case R.id.camera: 
       Toast.makeText(this, "Camera Pressed", Toast.LENGTH_SHORT).show(); 
       intent = new Intent(Warning.this, CameraOperations.class); 
       startActivity(intent); 
       return true; 

      default: 
       return super.onOptionsItemSelected(item); 
     } 
    } 

    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     if (keyCode == KeyEvent.KEYCODE_BACK) { 
      quitService = true; 
      mBluetoothLeService.disconnect(); 
      mBluetoothLeService.close(); 

      Intent intent = new Intent(Warning.this, Main.class); 
      intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(intent); 
      return true; 
     } 
     return super.onKeyDown(keyCode, event); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     mBluetoothLeService.disconnect(); 
     mBluetoothLeService.close(); 

     System.exit(0); 
    } 

    public boolean disconnectOperation(){ 
     this.quitService = true; 
     mBluetoothLeService.disconnect(); 
     mBluetoothLeService.close(); 
     return true; 
    } 

    private void checkWarning(byte[] byteArray) { 
     if (byteArray != null) { 
      for (int i = 0; i < byteArray.length; i++) { 
       if (byteArray[i] == 48) { 
        findLocation(); 
       } 
      } 
     } 
    } 

    private void getGattService(BluetoothGattService gattService) { 
     if (gattService == null) { 
      return; 
     } 

     BluetoothGattCharacteristic characteristicRx = gattService.getCharacteristic(HandleConnectionService.UUID_BLE_SHIELD_RX); 
     mBluetoothLeService.setCharacteristicNotification(characteristicRx, true); 
     mBluetoothLeService.readCharacteristic(characteristicRx); 
    } 

    private static IntentFilter makeGattUpdateIntentFilter() { 
     final IntentFilter intentFilter = new IntentFilter(); 
     intentFilter.addAction(HandleConnectionService.ACTION_GATT_CONNECTED); 
     intentFilter.addAction(HandleConnectionService.ACTION_GATT_DISCONNECTED); 
     intentFilter.addAction(HandleConnectionService.ACTION_GATT_SERVICES_DISCOVERED); 
     intentFilter.addAction(HandleConnectionService.ACTION_DATA_AVAILABLE); 
     intentFilter.addAction(CameraOperations.ACTION_PICTURE_RECEIVED); 

     return intentFilter; 
    } 

    private boolean checkGoogleServices() { 
     GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance(); 
     int available = googleAPI.isGooglePlayServicesAvailable(this); 
     if (available != ConnectionResult.SUCCESS) { 
      if (googleAPI.isUserResolvableError(available)) { 
       googleAPI.getErrorDialog(this, available, PLAY_SERVICES_REQUEST_TIME).show(); 
      } 
      return false; 
     } 

     return true; 
    } 

    public void findLocation() { 
     int REQUEST_CODE_ASK_PERMISSIONS = 123; 
     double latitude = 0.0; 
     double longitude = 0.0; 

     if(Build.VERSION.SDK_INT >= 23){ 
      boolean fineLocationAccess = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; 
      boolean courseLocationAccess = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED; 
      boolean accessGranted = fineLocationAccess && courseLocationAccess; 

      if (accessGranted) { 
       mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleClient); 
       if(mLastLocation != null) { 
        latitude = mLastLocation.getLatitude(); 
        longitude = mLastLocation.getLongitude(); 

        Toast.makeText(this, "latitude: " + latitude + " longitude: " + longitude, Toast.LENGTH_LONG).show(); 
       }else{ 
        Log.i("Warning", "Unable to get Location"); 
       } 
      }else{ 
       Log.i("Connection", "Request permission"); 
      } 
     }else{ 
      mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleClient); 
      if(mLastLocation != null) { 
       latitude = mLastLocation.getLatitude(); 
       longitude = mLastLocation.getLongitude(); 

       Toast.makeText(this, "latitude: " + latitude + " longitude: " + longitude, Toast.LENGTH_LONG).show(); 
      }else{ 
       Log.i("Warning", "Unable to get Location"); 
      } 
     } 
    } 

    public void buildGoogleApiClient() { 
     mGoogleClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API).build(); 
    } 

    @Override 
    public void onConnected(Bundle bundle) { 
     Log.w("Connected", " : " + mGoogleClient.isConnected()); 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Toast.makeText(this, "Location Services Stopped", Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) { 
     Toast.makeText(this, "Location Services Connection Fail", Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 

     if (mGoogleClient != null) { 
      mGoogleClient.connect(); 
     } 
    } 
} 

答えて

1

私はあなたのオリジナルのアイデアは、限り、あなたはそれを特定の方法を構築するとして、実際にはかなりの音だと思います。ロケーション情報について知っているアクティビティーは、他のアクティビティーとは独立してそのロケーションを更新および保管することができます。これは実際にx時間ごとに、または場所が変わるときに実際に実行されるサービスとして持つのが理想的でしょう。

同じクラスの中に、その位置情報の要求を処理する汎用ブロードキャスト受信者を持つことができます。ロケーション・データが各リクエスターが使用可能な方法で戻される限り、これを活用することもできる他のアプリケーション/アクティビティーを許可するという点で、これを汎用的なものにすることができます。

写真を撮るときのアクティビティから、写真を撮るときに、その場所の情報を要求するブロードキャストを送信することができます。複雑さの1つは、完了する前にこの位置情報を待つ時間を知ることです。このシナリオでは、ロケーション・アクティビティーは、正しく構成した場合に複数のアクティビティーがロケーション・データを要求できるという点で、一般化されたアクティビティーです。

潜在的に堅牢なアプローチの1つは、写真撮影活動を一般化されたものにすることです。これを行う1つの方法は、あなたが写真を撮るとき、あなたの写真アクティビティに、写真ファイルパス/ URI /識別情報を含むロケーションアクティビティにブロードキャストを送信させることができますが、あなたはレスポンスを待つことはありません。代わりに、ロケーションのアクティビティでこのブロードキャストをリッスンさせ、提供された識別情報を使用して写真のメタデータにその写真を検索します。このようにして、あなたの写真撮影アプリは、ロケーションアクティビティが終了するのを待つことなく立ち往生しません。

幸い、楽しいプロジェクトのように聞こえます。

+0

ありがとうございました!それはかなり楽しいプロジェクトです。アンドロイドへの良い再導入。新しいパターン/スタイルを学ぼうとするのは、ちょうどjavaよりも少し違った感じです。私はこれらのカップルを試してみて、どれが一番いいと感じるか見てみましょう。 – Ubarjohade

関連する問題