package mil.nga.dice; import android.content.ClipData; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; import android.webkit.MimeTypeMap; import android.widget.Toast; import com.ipaulpro.afilechooser.utils.FileUtils; import java.io.File; import mil.nga.dice.about.AboutActivity; import mil.nga.dice.about.DisclaimerDialogFragment; import mil.nga.dice.cardview.CardViewFragment; import mil.nga.dice.io.DICEFileUtils; import mil.nga.dice.map.ReportMapFragment; import mil.nga.dice.report.Report; import mil.nga.dice.report.ReportDetailActivity; import mil.nga.dice.report.ReportManager; /** * <h3>TODO:</h3> * <ol> * <li>fully test the activity life-cycle and the handling of the intent data for importing reports * <ul> * <li>proper life-cycle methods to implement</li> * <li>when getIntent() returns the expected data</li> * <li>leaving the activity with the home button</li> * <li>leaving the activity by the add content action</li> * <li>entering the activity from another app with the VIEW action</li> * <li>more ... ?</li> * </ul> * </li> * <li></li> * <li>add reports using <a href="http://developer.android.com/guide/topics/providers/document-provider.html">Storage Access Framework</a></li> * </ol> */ public class ReportCollectionActivity extends AppCompatActivity implements ReportCollectionCallbacks, DisclaimerDialogFragment.OnDisclaimerDialogDismissedListener, SwipeRefreshLayout.OnRefreshListener { public static final String TAG = "ReportCollection"; private static final String PREF_SHOW_DISCLAIMER = "show_disclaimer"; /** * Permissions request code for importing a GeoPackage as an external link */ public static final int PERMISSIONS_REQUEST_IMPORT_GEOPACKAGE = 200; /** * Permissions request code for reading / writing reports in external storage */ public static final int PERMISSIONS_REQUEST_REPORTS_ACCESS = 201; /** * Permissions request code for displaying overlay son the map */ public static final int PERMISSIONS_REQUEST_OVERLAYS = 202; /** * Intent activity request code when opening app settings */ public static final int ACTIVITY_APP_SETTINGS = 3344; public static final int OVERLAYS_ACTIVITY = 100; private static Boolean showDisclaimer = null; private int currentViewId = 0; private boolean handlingAddContent = false; /** * GeoPackage cache for importing GeoPackage files used to open DICE */ private GeoPackageCache geoPackageCache; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_report_collection); geoPackageCache = new GeoPackageCache(this); if (showDisclaimer == null) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); showDisclaimer = preferences.getBoolean(PREF_SHOW_DISCLAIMER, true); } if (showDisclaimer) { showDisclaimer = false; // don't show it again while the process lives DisclaimerDialogFragment dialogFragment = new DisclaimerDialogFragment(); dialogFragment.setCancelable(false); dialogFragment.show(getSupportFragmentManager(), "ReportCollectionActivity"); } if (savedInstanceState == null) { showCardView(); } if (savedInstanceState == null && !handlingAddContent) { handleIntentData(getIntent()); } } @Override public void onStop() { super.onStop(); } @Override public void onDestroy() { super.onDestroy(); } @Override protected void onRestart() { super.onRestart(); ReportManager.getInstance().refreshReports(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_report_collection, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_add_content) { handlingAddContent = true; Intent getContent = new Intent(Intent.ACTION_GET_CONTENT); getContent.addCategory(Intent.CATEGORY_OPENABLE); getContent.setType("*/*"); // TODO: test multiple getContent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); getContent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); getContent = Intent.createChooser(getContent, getString(R.string.action_add_content)); startActivityForResult(getContent, 0); return true; } else if (id == R.id.action_refresh) { onRefresh(); return true; } else if (id == R.id.action_about) { startAboutActivity(); return true; } return showCollectionViewForOptionItemId(id); } @Override public void reportSelectedToView(Report report) { if (!report.isEnabled()) { return; } // TODO: figure out more robust file type handling - what does Android offer? // Start the detail activity for the selected report if (report.getPath().isDirectory()) { Intent detailIntent = new Intent(this, ReportDetailActivity.class); detailIntent.putExtra("report", report); startActivity(detailIntent); } else { File reportPath = report.getPath(); Uri reportUri = Uri.fromFile(reportPath); String contentType = getContentResolver().getType(reportUri); if (contentType == null) { String ext = MimeTypeMap.getFileExtensionFromUrl(reportUri.getEncodedPath()); if (ext != null) { contentType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext); } } Intent viewContent = new Intent(Intent.ACTION_VIEW); viewContent.setDataAndType(reportUri, contentType); viewContent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); if (viewContent.resolveActivity(getPackageManager()) != null) { startActivity(viewContent); } else { Toast.makeText(this, R.string.no_viewer_for_report, Toast.LENGTH_SHORT).show(); } } } @Override public void onRefresh() { ReportManager.getInstance().refreshReports(this); } @Override public void onDisclaimerDialogAgree(DisclaimerDialogFragment disclaimerDialog) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); SharedPreferences.Editor editor = preferences.edit(); boolean show = disclaimerDialog.isShowDisclaimerChecked(); editor.putBoolean(PREF_SHOW_DISCLAIMER, show); editor.commit(); } @Override public void onDisclaimerDialogDisagree(DisclaimerDialogFragment disclaimerDialog) { showDisclaimer = true; SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); SharedPreferences.Editor editor = preferences.edit(); editor.remove(PREF_SHOW_DISCLAIMER); editor.commit(); finish(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { boolean handled = true; switch (requestCode) { case ACTIVITY_APP_SETTINGS: ReportManager.getInstance().refreshReports(this); break; case OVERLAYS_ACTIVITY: break; default: handled = false; } if (!handled) { if (resultCode != RESULT_OK) { return; } handleIntentData(data); } } private void handleIntentData(Intent intent) { Uri uri = intent.getData(); if (uri == null) { ClipData clipData = intent.getClipData(); if (clipData != null) { if (clipData.getItemCount() > 0) { ClipData.Item item = clipData.getItemAt(0); uri = item.getUri(); } } } if (uri == null) { return; } if ("dice".equals(uri.getScheme())) { // TODO: deep linking to specific report: navigateToReport(uri) } else { // Attempt to get a file path and display name String path = FileUtils.getPath(this, uri); String name = DICEFileUtils.getDisplayName(this, uri, path); // If a GeoPackage file if(geoPackageCache.hasGeoPackageExtension(name)){ geoPackageCache.importFile(name, uri, path); showMapView(); }else{ // Attempt to import a report ReportManager.getInstance().importReportFromUri(uri); } } } private void navigateToReport(Uri uri) { String srcScheme = uri.getQueryParameter("srcScheme"); String reportId = uri.getQueryParameter("reportID"); Report requestedReport = ReportManager.getInstance().getReportWithId(reportId); if (requestedReport != null) { Intent detailIntent = new Intent(this, ReportDetailActivity.class); detailIntent.putExtra("report", requestedReport); startActivity(detailIntent); } } private boolean showCollectionViewForOptionItemId(int id) { if (id == currentViewId) { return true; } if (currentViewId == R.id.action_about) { getSupportFragmentManager().popBackStackImmediate(); } currentViewId = id; if (id == R.id.collection_view_map) { showMapView(); } else if (id == R.id.collection_view_card) { showCardView(); } return currentViewId == id; } private void showMapView() { getSupportFragmentManager().beginTransaction() .replace(R.id.report_collection, new ReportMapFragment()) .commit(); } private void showCardView() { getSupportFragmentManager().beginTransaction() .replace(R.id.report_collection, new CardViewFragment()) .commit(); } private void startAboutActivity() { startActivity(new Intent(this, AboutActivity.class)); } /** * {@inheritDoc} */ @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { // Check if permission was granted boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; switch(requestCode) { case PERMISSIONS_REQUEST_IMPORT_GEOPACKAGE: geoPackageCache.importGeoPackageExternalLinkAfterPermissionGranted(granted); break; case PERMISSIONS_REQUEST_REPORTS_ACCESS: case PERMISSIONS_REQUEST_OVERLAYS: ReportManager.getInstance().refreshReportsWithPermissions(this, granted); break; } } }