Java tutorial
/* * The Martus(tm) free, social justice documentation and * monitoring software. Copyright (C) 2016, Beneficent * Technology, Inc. (Benetech). * * Martus is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later * version with the additions and exceptions described in the * accompanying Martus license file entitled "license.txt". * * It is distributed WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, including warranties of fitness of purpose or * merchantability. See the accompanying Martus License and * GPL license for more details on the required license terms * for this software. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */ package org.benetech.secureapp.activities; import android.app.Activity; import android.app.ListActivity; import android.app.LoaderManager.LoaderCallbacks; import android.content.ContentUris; import android.content.Context; import android.content.CursorLoader; import android.content.Intent; import android.content.Loader; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.Toast; import org.apache.commons.io.FileUtils; import org.benetech.secureapp.FormFromAssetFolderExtractor; import org.benetech.secureapp.MartusUploadManager; import org.benetech.secureapp.R; import org.benetech.secureapp.adapters.FormAdapter; import org.benetech.secureapp.adapters.FormAdapter.FormAdapterItemClickListener; import org.benetech.secureapp.application.AppConfig; import org.benetech.secureapp.application.Constants; import org.benetech.secureapp.application.MainApplication; import org.martus.android.library.common.dialog.ProgressDialogHandler; import org.martus.common.crypto.MartusCrypto; import org.odk.collect.android.application.Collect; import org.odk.collect.android.preferences.PreferencesActivity; import org.odk.collect.android.provider.FormsProviderAPI; import org.odk.collect.android.provider.InstanceProviderAPI; import java.io.File; import info.guardianproject.cacheword.CacheWordHandler; import info.guardianproject.cacheword.ICacheWordSubscriber; public class MainActivity extends ListActivity implements ICacheWordSubscriber, FormAdapterItemClickListener, LoaderCallbacks<Cursor>, MartusUploadManager.MartusUploadManagerCallback, LogoutActivityHandler { private static final String TAG = "MainActivity"; private CacheWordHandler cacheWordActivityHandler; private ProgressDialogHandler mProgressDialogHandler; private boolean isActivityPaused; public static final String ATTACHMENTS_FOLDER_NAME = "attachments"; public static final String GALLARY_FOLDER_NAME = "secureGallary"; public static final String CURRENT_FORM_ID_TAG = "currentFormId"; private static final int EXPORT_RECORDS_REQUEST_CODE = 100; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); cacheWordActivityHandler = new CacheWordHandler(this); mProgressDialogHandler = new ProgressDialogHandler(this); extractFormFromAssetFolderToSecureStorage(); initialiseExistingFormList(); enableOdkSwipeAndButtonNavigations(); setTitle(getString(R.string.app_name)); ((MainApplication) getApplication()).registerLogoutHandler(this); isActivityPaused = false; } @Override public void onUserInteraction() { ((MainApplication) getApplication()).resetInactivityTimer(); super.onUserInteraction(); } @Override public void logout() { cacheWordActivityHandler.lock(); cacheWordActivityHandler.detach(); cacheWordActivityHandler.disconnectFromService(); AppConfig.getInstance(getApplication()).getCrypto().clearKeyPair(); if (isActivityPaused()) return; Intent intent = new Intent(this, LoginActivity.class); finish(); startActivity(intent); } @Override public void onBackPressed() { logout(); super.onBackPressed(); } private void enableOdkSwipeAndButtonNavigations() { SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();//getString(PreferencesActivity.KEY_NAVIGATION editor.putString(PreferencesActivity.KEY_NAVIGATION, PreferencesActivity.NAVIGATION_SWIPE_BUTTONS); editor.commit(); } private void extractFormFromAssetFolderToSecureStorage() { try { new FormFromAssetFolderExtractor((MainApplication) getApplication()).extractXForm(); } catch (Exception e) { Log.e(TAG, getString(R.string.error_message_copying_assets_to_secure_storage_failed), e); } } @Override protected void onResume() { super.onResume(); isActivityPaused = false; cacheWordActivityHandler.connectToService(); ((MainApplication) getApplication()).enableInactivityTimer(); } @Override protected void onPause() { super.onPause(); isActivityPaused = true; cacheWordActivityHandler.disconnectFromService(); } private boolean isActivityPaused() { return isActivityPaused; } private void initialiseExistingFormList() { FormAdapter adapter = new FormAdapter(this.getApplicationContext(), null, this); setListAdapter(adapter); getLoaderManager().initLoader(0, null, (LoaderCallbacks<Cursor>) this); } /** * Stores the path of selected instance in the parent class and finishes. */ @Override protected void onListItemClick(ListView listView, View view, int position, long id) { Cursor cursor = (Cursor) getListAdapter().getItem(position); startManagingCursor(cursor); Uri instanceUri = ContentUris.withAppendedId(InstanceProviderAPI.InstanceColumns.CONTENT_URI, cursor.getLong(cursor.getColumnIndex(InstanceProviderAPI.InstanceColumns._ID))); Collect.getInstance().getActivityLogger().logAction(this, "onListItemClick", instanceUri.toString()); String action = getIntent().getAction(); if (Intent.ACTION_PICK.equals(action)) { // caller is waiting on a picked form setResult(RESULT_OK, new Intent().setData(instanceUri)); } else { // the form can be edited if it is incomplete or if, when it was // marked as complete, it was determined that it could be edited // later. String status = cursor.getString(cursor.getColumnIndex(InstanceProviderAPI.InstanceColumns.STATUS)); String canEditWhenCompleteSetting = cursor .getString(cursor.getColumnIndex(InstanceProviderAPI.InstanceColumns.CAN_EDIT_WHEN_COMPLETE)); boolean canEdit = status.equals(InstanceProviderAPI.STATUS_INCOMPLETE) || Boolean.parseBoolean(canEditWhenCompleteSetting); if (canEdit) { startForm(instanceUri); } } } public void startNewForm(View view) { try { Uri formUri = ContentUris.withAppendedId(FormsProviderAPI.FormsColumns.CONTENT_URI, 1); startForm(formUri); } catch (Exception e) { Log.e(Constants.LOG_LABEL, getString(R.string.error_message_problem_finding_form_file), e); } } private void startForm(Uri formUri) { ((MainApplication) getApplication()).disableInactivityTimer(); Intent intent = new Intent(this, MainFormEntryActivity.class); intent.setData(formUri); Cursor cursor = getContentResolver().query(FormsProviderAPI.FormsColumns.CONTENT_URI, null, null, null, null); printContentResolver(cursor); startActivity(intent); } private void printContentResolver(Cursor cursor) { cursor.moveToFirst(); // System.out.println("===========================================START"); // for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) // { // System.out.println("==========================================="); // String[] columnNames = cursor.getColumnNames(); // for (int index = 0; index < columnNames.length; ++index) { // System.out.println("---------------------------COLUMN name = " + columnNames[index]); // // int nameColumn = cursor.getColumnIndex(columnNames[index]); // // String name = cursor.getString(nameColumn); // System.out.println("---------------------------- COL Value = " + name); // System.out.println("-------------------------------------------------------------------------"); // } // System.out.println("==========================================="); // } // System.out.println("===========================================END"); } @Override public void onCacheWordUninitialized() { } @Override public void onCacheWordLocked() { } @Override public void onCacheWordOpened() { } @Override public void onSyncRequested(Cursor form) { if (!isNetworkAvailable()) { Util.showErrorMessage(this, getString(R.string.no_network_connection)); return; } showProgressDialog(getString(R.string.syncing_form)); MartusUploadManager martusUploadManager = new MartusUploadManager(this); martusUploadManager.setMartusUploadCallback(this); martusUploadManager.uploadInstanceFormFromCursor(form, cacheWordActivityHandler); // We also store the form to upload in this Activity in case Util.uploadForm fails // because we don't have a server keypair generated. In that case, we'll have to // wait until UploadRightsTask completes and notifies us to retry upload on processMagicWordResponse() // setFormToUpload(form); // showProgressDialog(getString(R.string.progress_preparing_to_connect)); // Util.uploadForm(this, form, this, cacheWordActivityHandler.getEncryptionKey()); } public boolean isNetworkAvailable() { ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService( Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); return networkInfo != null; } @Override public void onDeleteRequested(Cursor form) { form.moveToFirst(); int idColumnIndex = form.getColumnIndex(InstanceProviderAPI.InstanceColumns._ID); String formId = form.getString(idColumnIndex); int deleteCount = getContentResolver().delete(InstanceProviderAPI.InstanceColumns.CONTENT_URI, InstanceProviderAPI.InstanceColumns._ID + " = ?", new String[] { formId }); form.moveToFirst(); int instancefilepathColumnIndex = form .getColumnIndex(InstanceProviderAPI.InstanceColumns.INSTANCE_FILE_PATH); String instanceFilepath = form.getString(instancefilepathColumnIndex); deleteOdkInstanceCacheDir(instanceFilepath); Log.i(TAG, "Instance form deleted. Delete count = " + deleteCount); form.close(); } public static void deleteOdkInstanceCacheDir(String instancePath) { File odkInstanceDir = new File(instancePath); try { FileUtils.deleteDirectory(odkInstanceDir); if (odkInstanceDir.exists()) Log.e(TAG, "odk form instance dir was not deleted : " + instancePath); else Log.i(TAG, "odk form instance dir deleted successfully:" + instancePath); } catch (Exception e) { Log.e(TAG, "Exception during deletion of dir: " + odkInstanceDir, e); } } @Override public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) { String selection = InstanceProviderAPI.InstanceColumns.STATUS + " != ?"; String[] selectionArgs = { InstanceProviderAPI.STATUS_SUBMITTED }; String sortOrder = InstanceProviderAPI.InstanceColumns.STATUS + " DESC, " + InstanceProviderAPI.InstanceColumns.DISPLAY_NAME + " ASC"; return new CursorLoader(this, InstanceProviderAPI.InstanceColumns.CONTENT_URI, null, selection, selectionArgs, sortOrder); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { ((SimpleCursorAdapter) getListAdapter()).swapCursor(data); } @Override public void onLoaderReset(Loader<Cursor> arg0) { ((SimpleCursorAdapter) getListAdapter()).swapCursor(null); } public void showCreatingMartusCryptoErrorMessage() { Util.showErrorMessage(this, getString(R.string.error_create_account), getString(R.string.error_message)); } public static void showShortToast(Context contenxt, String message) { Toast.makeText(contenxt, message, Toast.LENGTH_SHORT).show(); } private void showProgressDialog(String message) { getProgressDialogHandler().showProgressDialog(message); } private void dismissProgressDialog() { getProgressDialogHandler().dismissProgressDialog(); } private ProgressDialogHandler getProgressDialogHandler() { return mProgressDialogHandler; } @Override public void onMartusUploadSuccess() { dismissProgressDialog(); } @Override public void onMartusUploadError(MartusError error) { dismissProgressDialog(); switch (error) { case CREATE_KEYPAIR_FAILURE: Util.showErrorMessage(this, getString(R.string.keypair_creation_failed)); break; case INVALID_DEFAULT_SERVER_IP: Util.showErrorMessage(this, getString(R.string.invalid_server_ip)); break; case NO_NETWORK: Util.showErrorMessage(this, getString(R.string.no_network_connection)); break; case INVALID_SERVER_RESPONSE: Util.showErrorMessage(this, getString(R.string.invalid_server_info)); break; case INVALID_SERVER_PUB_KEY: Util.showErrorMessage(this, getString(R.string.invalid_server_public_code)); break; } } @Override public void onManageAttachments(Cursor form) { Intent intent = new Intent(this, ManageAttachmentsActivty.class); form.moveToFirst(); int idColumnIndex = form.getColumnIndex(InstanceProviderAPI.InstanceColumns._ID); String formId = form.getString(idColumnIndex); intent.putExtra(CURRENT_FORM_ID_TAG, formId); startActivity(intent); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.show_version_menu_item) { showVersionNumberAsToast(this); return true; } if (id == R.id.show_receiving_contact_public_key_menu_item) { showReceivingContactPublicKey(this); return true; } if (id == R.id.menu_item_account_information) { Intent intent = new Intent(this, AccountInformationActivity.class); startActivity(intent); return true; } if (id == R.id.menu_item_export_all_records) { exportRecordAllRecords(); return true; } return super.onOptionsItemSelected(item); } public static void showReceivingContactPublicKey(Activity context) { try { String desktopPublicKey = context.getString(R.string.public_key_desktop); String publicCode40 = MartusCrypto.computeFormattedPublicCode40(desktopPublicKey); Util.showMessage(context, publicCode40, context.getString(R.string.receiving_contact_public_key)); } catch (Exception e) { Log.e(TAG, "Could not format public key", e); showShortToast(context, context.getString(R.string.error_message)); } } public static void showVersionNumberAsToast(Context context) { String versionLabel; try { PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); String versionNameLabel = context.getString(R.string.version_name_label, pInfo.versionName); String versionCodeLabel = context.getString(R.string.version_code_label, pInfo.versionCode); versionLabel = versionNameLabel + "\n" + versionCodeLabel; } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, e.getMessage(), e); versionLabel = "Error"; } Toast.makeText(context, versionLabel, Toast.LENGTH_LONG).show(); } public void exportRecordAllRecords() { Cursor cursor = getContentResolver().query(InstanceProviderAPI.InstanceColumns.CONTENT_URI, null, null, null, null); cursor.moveToFirst(); for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { int formLabelColumnIndex = cursor.getColumnIndex(InstanceProviderAPI.InstanceColumns.DISPLAY_NAME); int displaySubTextColumnIndex = cursor .getColumnIndex(InstanceProviderAPI.InstanceColumns.DISPLAY_SUBTEXT); int instancefilepathColumnIndex = cursor .getColumnIndex(InstanceProviderAPI.InstanceColumns.INSTANCE_FILE_PATH); int formIdColumnIndex = cursor.getColumnIndex(InstanceProviderAPI.InstanceColumns._ID); SharedPreferences sharedPref = getApplicationContext() .getSharedPreferences(AccountInformationActivity.PRFERENCES_FILE_NAME, Context.MODE_PRIVATE); String authorName = sharedPref.getString(AccountInformationActivity.AUTHOR_PREFERENCES_KEY, ""); String organizationName = sharedPref.getString(AccountInformationActivity.ORGANIZATION_PREFRENCES_KEY, ""); Intent intent = new Intent(this, BulletinToMbaFileExporter.class); intent.putExtra(MartusUploadManager.BULLETIN_DISPLAY_NAME_TAG, cursor.getString(formLabelColumnIndex)); intent.putExtra(MartusUploadManager.BULLETIN_SUB_DISPLAY_NAME_TAG, cursor.getString(displaySubTextColumnIndex)); intent.putExtra(MartusUploadManager.BULLETIN_ISTANCE_FILE_PATH_TAG, cursor.getString(instancefilepathColumnIndex)); intent.putExtra(MartusUploadManager.BULLETIN_FORM_ID_TAG, cursor.getString(formIdColumnIndex)); intent.putExtra(MartusUploadManager.BULLETIN_AUTHOR_TAG, authorName); intent.putExtra(MartusUploadManager.BULLETIN_ORGANIZATION_TAG, organizationName); startActivityForResult(intent, EXPORT_RECORDS_REQUEST_CODE); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == EXPORT_RECORDS_REQUEST_CODE) displayMessages(resultCode); super.onActivityResult(requestCode, resultCode, data); } private void displayMessages(int resultCode) { int messageId = R.string.message_export_all_records_successful; if (resultCode == Activity.RESULT_CANCELED) { messageId = R.string.message_export_all_records_unsuccessful; } Toast.makeText(this, getString(messageId), Toast.LENGTH_LONG).show(); } }