package fr.tvbarthel.apps.sayitfromthesky.activities; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.Canvas; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.content.FileProvider; import android.util.Log; import android.view.View; import android.view.ViewTreeObserver; import android.widget.TextView; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.UiSettings; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.PolylineOptions; import com.google.maps.android.PolyUtil; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnClick; import fr.tvbarthel.apps.sayitfromthesky.R; import fr.tvbarthel.apps.sayitfromthesky.fragments.SayItMapFragment; import fr.tvbarthel.apps.sayitfromthesky.fragments.dialogs.EditDrawingDialog; import fr.tvbarthel.apps.sayitfromthesky.helpers.ViewHelper; import fr.tvbarthel.apps.sayitfromthesky.models.Drawing; public class DrawingViewerActivity extends FragmentActivity implements SayItMapFragment.Callback, EditDrawingDialog.Callback { public static final String EXTRA_KEY_DRAWING = "DrawingViewerActivity.Extra.Key.Drawing"; private static final String FRAGMENT_TAG_MAP = "DrawingViewerActivity.Fragment.Tag.Map"; private static final String TAG = DrawingViewerActivity.class.getSimpleName(); @InjectView(R.id.activity_drawing_viewer_drawing_length) TextView mDrawingLength; @InjectView(R.id.activity_drawing_viewer_drawing_title) TextView mDrawingTitle; @InjectView(R.id.activity_drawing_viewer_header) View mHeader; @InjectView(R.id.activity_drawing_viewer_edit_action) View mEditAction; @InjectView(R.id.activity_drawing_viewer_share_action) View mShareAction; private SayItMapFragment mMapFragment; private GoogleMap mGoogleMap; private PolylineOptions mPathOptions; private Drawing mDrawing; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_drawing_viewer); ButterKnife.inject(this); // Create a PolylineOptions to draw the paths mPathOptions = new PolylineOptions(); mPathOptions.color(getResources().getColor(R.color.primary_color)); mDrawing = getDrawing(); createMapFragment(); mDrawingTitle.setText(mDrawing.getTitle()); ViewHelper.slideFromBottom(mShareAction); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } @Override public void onMapReady() { if (mGoogleMap == null) { mGoogleMap = mMapFragment.getMap(); if (mGoogleMap != null) { // You are good to use the map =) final UiSettings uiSettings = mGoogleMap.getUiSettings(); uiSettings.setCompassEnabled(false); uiSettings.setZoomControlsEnabled(false); // Draw the paths if (!mDrawing.getEncodedPolylines().isEmpty()) { final LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder(); for (String encodedPath : mDrawing.getEncodedPolylines()) { final List<LatLng> pathPoints = PolyUtil.decode(encodedPath); mGoogleMap.addPolyline(mPathOptions).setPoints(pathPoints); for (LatLng point : pathPoints) { boundsBuilder.include(point); } } animateCameraToBounds(boundsBuilder.build()); mDrawingLength.setText(getString(R.string.activity_drawing_viewer_drawing_length, mDrawing.getLength())); } } } } private Drawing getDrawing() { Drawing drawing = Drawing.EMPTY; final Bundle extras = getIntent().getExtras(); if (extras != null && extras.containsKey(EXTRA_KEY_DRAWING)) { drawing = extras.getParcelable(EXTRA_KEY_DRAWING); } return drawing; } private void createMapFragment() { mMapFragment = (SayItMapFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_MAP); if (mMapFragment == null) { // Create a new map fragment. mMapFragment = new SayItMapFragment(); getSupportFragmentManager().beginTransaction().add(R.id.activity_drawing_viewer_map_container, mMapFragment, FRAGMENT_TAG_MAP).commit(); } else { // Re-use the old map fragment. getSupportFragmentManager().beginTransaction().show(mMapFragment).commit(); } } private void animateCameraToBounds(final LatLngBounds bounds) { try { mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50)); } catch (IllegalStateException e) { // layout not yet initialized final View mapView = mMapFragment.getView(); if (mapView.getViewTreeObserver().isAlive()) { mapView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { ViewHelper.removeOnGlobalLayoutListener(mapView, this); mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50)); } }); } } } /** * Handle the share action. * * @return true to consume the action, false otherwise. */ @OnClick(R.id.activity_drawing_viewer_share_action) void handleShareAction() { // TODO if (mGoogleMap != null) { mGoogleMap.snapshot(new GoogleMap.SnapshotReadyCallback() { @Override public void onSnapshotReady(Bitmap bitmap) { mEditAction.setVisibility(View.INVISIBLE); final Canvas canvas = new Canvas(bitmap); mHeader.draw(canvas); mEditAction.setVisibility(View.VISIBLE); final Uri snapshotUri = saveSnapshotToTempFile(bitmap); if (snapshotUri != null) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_STREAM, snapshotUri); intent.setType("image/jpeg"); // Grant permissions to all apps that can handle this intent // thanks to this answer http://stackoverflow.com/a/18332000 List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { final String packageName = resolveInfo.activityInfo.packageName; grantUriPermission(packageName, snapshotUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); } // And start startActivity(Intent.createChooser(intent, getString(R.string.activity_drawing_viewer_chooser_title_snapshots))); } } }); } } /** * Handle the edit action. * * @return true to consume the action, false otherwise. */ @OnClick(R.id.activity_drawing_viewer_edit_action) void handleEditAction() { EditDrawingDialog.newInstance(mDrawing).show(getSupportFragmentManager(), null); } /** * Save a snapshot to temporary file in internal storage. * * @param bitmap the {@link android.graphics.Bitmap} that will be saved. * @return a Content URI that can be served to another app {@see http://developer.android.com/reference/android/support/v4/content/FileProvider.html} */ private Uri saveSnapshotToTempFile(Bitmap bitmap) { final ByteArrayOutputStream bytesStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytesStream); try { final File snapshotPath = new File(getFilesDir(), "snapshots"); if (!snapshotPath.isDirectory()) snapshotPath.mkdirs(); final File file = new File(snapshotPath, "temp_snapshot.jpg"); final FileOutputStream outputStream = new FileOutputStream(file); outputStream.write(bytesStream.toByteArray()); outputStream.close(); return FileProvider.getUriForFile(this, "fr.tvbarthel.apps.sayitfromthesky.fileprovider", file); } catch (IOException e) { Log.e(TAG, "saveSnapshotToTempFile error", e); return null; } } @Override public void onDrawingEdited(Drawing drawing) { // At the moment, only the title can be edited. // So we only change the title in the action bar. mDrawing = drawing; mDrawingTitle.setText(mDrawing.getTitle()); } }