package org.commcare.activities; import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.net.wifi.p2p.WifiP2pConfig; import android.net.wifi.p2p.WifiP2pDevice; import android.net.wifi.p2p.WifiP2pManager; import android.net.wifi.p2p.WifiP2pManager.ActionListener; import android.net.wifi.p2p.WifiP2pManager.Channel; import android.net.wifi.p2p.WifiP2pManager.PeerListListener; import android.os.Build; import android.os.Bundle; import android.support.v4.app.FragmentTransaction; import android.util.Log; import android.util.Pair; import android.widget.TextView; import android.widget.Toast; import org.commcare.CommCareApplication; import org.commcare.android.adapters.WiFiDirectUIController; import org.commcare.dalvik.R; import org.commcare.fragments.DeviceDetailFragment; import org.commcare.fragments.DeviceListFragment; import org.commcare.fragments.DeviceListFragment.DeviceActionListener; import org.commcare.fragments.FileServerFragment; import org.commcare.fragments.FileServerFragment.FileServerListener; import org.commcare.fragments.WiFiDirectManagementFragment; import org.commcare.fragments.WiFiDirectManagementFragment.WifiDirectManagerListener; import org.commcare.interfaces.CommCareActivityUIController; import org.commcare.interfaces.WithUIController; import org.commcare.logging.AndroidLogger; import org.commcare.models.database.SqlStorage; import org.commcare.android.database.user.models.FormRecord; import org.commcare.preferences.CommCareServerPreferences; import org.commcare.services.WiFiDirectBroadcastReceiver; import org.commcare.tasks.FormRecordToFileTask; import org.commcare.tasks.FormTransferTask; import org.commcare.tasks.SendTask; import org.commcare.tasks.UnzipTask; import org.commcare.tasks.WipeTask; import org.commcare.tasks.ZipTask; import org.commcare.tasks.templates.CommCareTask; import org.commcare.utils.FileUtil; import org.commcare.utils.FormUploadResult; import org.commcare.utils.StorageUtils; import org.commcare.views.dialogs.StandardAlertDialog; import org.commcare.views.dialogs.CustomProgressDialog; import org.javarosa.core.services.Logger; import org.javarosa.core.services.locale.Localization; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Vector; /** * An activity that uses WiFi Direct APIs to discover and connect with available * devices. WiFi Direct APIs are asynchronous and rely on callback mechanism * using interfaces to notify the application of operation success or failure. * The application should also register a BroadcastReceiver for notification of * WiFi state related events. */ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class CommCareWiFiDirectActivity extends SessionAwareCommCareActivity<CommCareWiFiDirectActivity> implements DeviceActionListener, FileServerListener, WifiDirectManagerListener, WithUIController { private static final String TAG = CommCareWiFiDirectActivity.class.getSimpleName(); private WifiP2pManager mManager; private Channel mChannel; private WiFiDirectBroadcastReceiver mReceiver; private IntentFilter mIntentFilter; public enum wdState {send, receive, submit} private WiFiDirectUIController uiController; private static String baseDirectory; private static String toBeTransferredDirectory; private static String zipFilePath; private static String receiveDirectory; private static String receiveZipDirectory; private static String toBeSubmittedDirectory; private TextView myStatusText; private TextView formCountText; private TextView stateHeaderText; private TextView stateStatusText; private static final int FILE_SERVER_TASK_ID = 129123; private wdState mState = wdState.send; private FormRecord[] cachedRecords; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.wifi_direct_main); myStatusText = (TextView)this.findViewById(R.id.my_status_text); formCountText = (TextView)this.findViewById(R.id.form_count_text); stateStatusText = (TextView)this.findViewById(R.id.wifi_state_status); stateHeaderText = (TextView)this.findViewById(R.id.wifi_state_header); String baseDir = this.getFilesDir().getAbsolutePath(); baseDirectory = baseDir + "/" + Localization.get("wifi.direct.base.folder"); // these are the two folders where form record folders can live. toBeTransferredDirectory = baseDirectory + "/transfer"; toBeSubmittedDirectory = baseDirectory + "/submit"; // these are temporary paths for storing received and unzipped forms zipFilePath = baseDirectory + "/formRecordZip.zip"; receiveDirectory = baseDirectory + "/receive"; receiveZipDirectory = receiveDirectory + "/zipDest"; mManager = (WifiP2pManager)getSystemService(Context.WIFI_P2P_SERVICE); mChannel = mManager.initialize(this, getMainLooper(), null); mIntentFilter = new IntentFilter(); mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); if (savedInstanceState == null) { showChangeStateDialog(); } uiController.setupUI(); } @Override public void initUIController() { uiController = new WiFiDirectUIController(this); } @Override public CommCareActivityUIController getUIController() { return this.uiController; } public void showChangeStateDialog() { showDialog(this, localize("wifi.direct.change.state.title").toString(), localize("wifi.direct.change.state.text").toString()); } /** * register the broadcast receiver */ @Override protected void onResumeSessionSafe() { Logger.log(TAG, "resuming wi-fi direct activity"); final WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment)getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); mReceiver = new WiFiDirectBroadcastReceiver(mManager, fragment); registerReceiver(mReceiver, mIntentFilter); fragment.startReceiver(mManager, mChannel); changeState(); } /** * unregister the broadcast receiver */ @Override protected void onPause() { super.onPause(); Logger.log(TAG, "Pausing wi-fi direct activity"); unregisterReceiver(mReceiver); } private void hostGroup() { Logger.log(TAG, "Hosting Wi-fi direct group"); final FileServerFragment fsFragment = (FileServerFragment)getSupportFragmentManager() .findFragmentById(R.id.file_server_fragment); fsFragment.startServer(receiveZipDirectory); WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment)getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); if (!fragment.isWifiP2pEnabled()) { Logger.log(TAG, "returning because Wi-fi direct is not available"); Toast.makeText(CommCareWiFiDirectActivity.this, localize("wifi.direct.wifi.direct.off"), Toast.LENGTH_SHORT).show(); return; } mManager.createGroup(mChannel, fragment); } private void changeState() { updateStatusText(); uiController.refreshView(); } private void showDialog(Activity activity, String title, String message) { StandardAlertDialog d = new StandardAlertDialog(activity, title, message); DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case AlertDialog.BUTTON_POSITIVE: beSubmitter(); break; case AlertDialog.BUTTON_NEUTRAL: beReceiver(); break; case AlertDialog.BUTTON_NEGATIVE: beSender(); break; } dismissAlertDialog(); } }; d.setNeutralButton(localize("wifi.direct.receive.forms"), listener); d.setNegativeButton(localize("wifi.direct.transfer.forms"), listener); d.setPositiveButton(localize("wifi.direct.submit.forms"), listener); showAlertDialog(d); } private void beSender() { myStatusText.setText(localize("wifi.direct.enter.send.mode")); WiFiDirectManagementFragment wifiFragment = (WiFiDirectManagementFragment)getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); DeviceListFragment fragmentList = (DeviceListFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_list); DeviceDetailFragment fragmentDetails = (DeviceDetailFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_detail); FileServerFragment fsFragment = (FileServerFragment)getSupportFragmentManager() .findFragmentById(R.id.file_server_fragment); FragmentTransaction tr = getSupportFragmentManager().beginTransaction(); tr.show(wifiFragment); tr.show(fragmentList); tr.show(fragmentDetails); tr.hide(fsFragment); tr.commit(); wifiFragment.setIsHost(false); wifiFragment.resetConnectionGroup(); Logger.log(TAG, "Device designated as sender"); resetData(); mState = wdState.send; changeState(); } private void beReceiver() { Logger.log(AndroidLogger.TYPE_FORM_DUMP, "Became receiver"); myStatusText.setText(localize("wifi.direct.enter.receive.mode")); WiFiDirectManagementFragment wifiFragment = (WiFiDirectManagementFragment)getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); DeviceListFragment fragmentList = (DeviceListFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_list); DeviceDetailFragment fragmentDetails = (DeviceDetailFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_detail); FileServerFragment fsFragment = (FileServerFragment)getSupportFragmentManager() .findFragmentById(R.id.file_server_fragment); FragmentTransaction tr = getSupportFragmentManager().beginTransaction(); tr.show(wifiFragment); tr.show(fragmentList); tr.show(fragmentDetails); tr.show(fsFragment); tr.commit(); wifiFragment.setIsHost(true); wifiFragment.resetConnectionGroup(); Logger.log(TAG, "Device designated as receiver"); resetData(); hostGroup(); mState = wdState.receive; changeState(); } private void beSubmitter() { Logger.log(AndroidLogger.TYPE_FORM_DUMP, "Became submitter"); unzipFilesHelper(); myStatusText.setText(localize("wifi.direct.enter.submit.mode")); WiFiDirectManagementFragment wifiFragment = (WiFiDirectManagementFragment)getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); DeviceListFragment fragmentList = (DeviceListFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_list); DeviceDetailFragment fragmentDetails = (DeviceDetailFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_detail); FileServerFragment fsFragment = (FileServerFragment)getSupportFragmentManager() .findFragmentById(R.id.file_server_fragment); FragmentTransaction tr = getSupportFragmentManager().beginTransaction(); tr.hide(fsFragment); tr.hide(wifiFragment); tr.hide(fragmentList); tr.hide(fragmentDetails); tr.commit(); wifiFragment.setIsHost(false); wifiFragment.resetConnectionGroup(); mState = wdState.submit; changeState(); } private void cleanPostSend() { Logger.log(TAG, "cleaning forms after successful Wi-fi direct transfer"); // remove Forms from CC WipeTask mWipeTask = new WipeTask(getApplicationContext(), this.cachedRecords) { @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, Boolean result) { receiver.onCleanSuccessful(); } @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], WipeTask.WIPE_TASK_ID); receiver.myStatusText.setText(update[0]); } @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { receiver.myStatusText.setText(localize("wifi.direct.error.wiping.forms", e.getMessage())); receiver.transplantStyle(myStatusText, R.layout.template_text_notification_problem); } }; mWipeTask.connect(CommCareWiFiDirectActivity.this); mWipeTask.execute(); FileUtil.deleteFileOrDir(new File(toBeTransferredDirectory)); FileUtil.deleteFileOrDir(new File(zipFilePath)); Logger.log(TAG, "Deleting dirs " + toBeTransferredDirectory + " and " + zipFilePath); this.cachedRecords = null; } private void onCleanSuccessful() { Logger.log(TAG, "clean successful"); updateStatusText(); } public void submitFiles() { Logger.log(TAG, "submitting forms in Wi-fi direct activity"); unzipFilesHelper(); final String url = this.getString(R.string.PostURL); File receiveFolder = new File(toBeSubmittedDirectory); if (!receiveFolder.isDirectory() || !receiveFolder.exists()) { myStatusText.setText(Localization.get("wifi.direct.submit.missing", new String[]{receiveFolder.getPath()})); } File[] files = receiveFolder.listFiles(); if (files == null) { myStatusText.setText(localize("wifi.direct.error.no.forms")); transplantStyle(myStatusText, R.layout.template_text_notification_problem); return; } final int formsOnSD = files.length; //if there're no forms to submit, just return if (formsOnSD == 0) { myStatusText.setText(Localization.get("bulk.form.no.unsynced")); transplantStyle(myStatusText, R.layout.template_text_notification_problem); return; } SharedPreferences settings = CommCareApplication.instance().getCurrentApp().getAppPreferences(); SendTask<CommCareWiFiDirectActivity> mSendTask = new SendTask<CommCareWiFiDirectActivity>( settings.getString(CommCareServerPreferences.PREFS_SUBMISSION_URL_KEY, url), receiveFolder) { @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, Boolean result) { if (result == Boolean.TRUE) { Intent i = new Intent(getIntent()); i.putExtra(AdvancedActionsActivity.KEY_NUMBER_DUMPED, formsOnSD); receiver.setResult(BULK_SEND_ID, i); Logger.log(TAG, "Sucessfully dumped " + formsOnSD); receiver.finish(); } else { //assume that we've already set the error message, but make it look scary receiver.transplantStyle(myStatusText, R.layout.template_text_notification_problem); } } @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], BULK_SEND_ID); receiver.myStatusText.setText(update[0]); } @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { Logger.log(TAG, "Error submitting forms in wi-fi direct with exception" + e.getMessage()); receiver.myStatusText.setText(Localization.get("bulk.form.error", new String[]{e.getMessage()})); receiver.transplantStyle(myStatusText, R.layout.template_text_notification_problem); } }; mSendTask.connect(CommCareWiFiDirectActivity.this); mSendTask.execute(); } private boolean unzipFilesHelper() { File receiveZipDir = new File(receiveDirectory); if (!receiveZipDir.exists() || !(receiveZipDir.isDirectory())) { return false; } File[] zipDirContents = receiveZipDir.listFiles(); if (zipDirContents.length < 1) { return false; } myStatusText.setText(localize("wifi.direct.zip.unzipping")); for (File zipDirContent : zipDirContents) { unzipFiles(zipDirContent.getAbsolutePath()); } return true; } private void unzipFiles(String fn) { Logger.log(TAG, "Unzipping files in Wi-fi direct"); UnzipTask<CommCareWiFiDirectActivity> mUnzipTask = new UnzipTask<CommCareWiFiDirectActivity>() { @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, Integer result) { Log.d(TAG, "delivering unzip result"); if (result > 0) { receiver.onUnzipSuccessful(result); } else { //assume that we've already set the error message, but make it look scary receiver.transplantStyle(myStatusText, R.layout.template_text_notification_problem); } } @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { Log.d(TAG, "delivering unzip upate"); receiver.updateProgress(update[0], CommCareTask.GENERIC_TASK_ID); receiver.myStatusText.setText(update[0]); } @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { Log.d(TAG, "unzip deliver error: " + e.getMessage()); receiver.myStatusText.setText(Localization.get("mult.install.error", new String[]{e.getMessage()})); receiver.transplantStyle(myStatusText, R.layout.template_text_notification_problem); } }; mUnzipTask.connect(CommCareWiFiDirectActivity.this); Logger.log(TAG, "executing task with: " + fn + " , " + toBeSubmittedDirectory); mUnzipTask.execute(fn, toBeSubmittedDirectory); } /* if successful, broadcasts WIFI_P2P_Peers_CHANGED_ACTION intent with list of peers * received in WiFiDirectBroadcastReceiver class */ public void discoverPeers() { Logger.log(TAG, "Discovering Wi-fi direct peers"); WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment)getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); if (!fragment.isWifiP2pEnabled()) { Toast.makeText(CommCareWiFiDirectActivity.this, localize("wifi.direct.wifi.direct.off"), Toast.LENGTH_SHORT).show(); return; } final DeviceListFragment dlFragment = (DeviceListFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_list); dlFragment.onInitiateDiscovery(); mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { Toast.makeText(CommCareWiFiDirectActivity.this, localize("wifi.direct.discovery.start"), Toast.LENGTH_SHORT).show(); } @Override public void onFailure(int reasonCode) { Logger.log(TAG, "Discovery of Wi-fi peers failed"); if (reasonCode == 0 || reasonCode == 2) { Toast.makeText(CommCareWiFiDirectActivity.this, localize("wifi.direct.discovery.failed.generic"), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(CommCareWiFiDirectActivity.this, localize("wifi.direct.discovery.failed.specific", "" + reasonCode), Toast.LENGTH_SHORT).show(); } } }); } @Override public void resetData() { DeviceListFragment fragmentList = (DeviceListFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_list); DeviceDetailFragment fragmentDetails = (DeviceDetailFragment)getSupportFragmentManager() .findFragmentById(R.id.frag_detail); if (fragmentList != null) { fragmentList.clearPeers(); } if (fragmentDetails != null) { fragmentDetails.resetViews(); } } @Override public void connect(WifiP2pConfig config) { Logger.log(TAG, "connecting to wi-fi peer"); mManager.connect(mChannel, config, new ActionListener() { @Override public void onSuccess() { myStatusText.setText(localize("wifi.direct.connect.success")); } @Override public void onFailure(int reason) { Logger.log(TAG, "Connection to peer failed"); Toast.makeText(CommCareWiFiDirectActivity.this, localize("wifi.direct.connect.failed"), Toast.LENGTH_SHORT).show(); } }); } private static void deleteIfExists(String filePath) { File toDelete = new File(filePath); if (toDelete.exists()) { toDelete.delete(); } } public void prepareFileTransfer() { Logger.log(TAG, "Preparing File Transfer"); CommCareWiFiDirectActivity.deleteIfExists(zipFilePath); final WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment)getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); if (!fragment.getDeviceConnected()) { myStatusText.setText(localize("wifi.direct.no.group")); return; } moveFormRecordsToFiles(); } private void moveReceivedFiles() { File receiveFolder = new File(toBeSubmittedDirectory); if (!receiveFolder.isDirectory() || !receiveFolder.exists()) { // we haven't received any transfers, just return. return; } // We've received transferred forms. Move them into the to be zipped directory. File[] originFiles = receiveFolder.listFiles(); File[] destinationFiles = new File[originFiles.length]; for(int i=0; i< originFiles.length; i++){ destinationFiles[i] = new File(toBeTransferredDirectory, originFiles[i].getName()); } try { Log.d(TAG, "We have " + originFiles.length + " toBeSubmitted files to transfer"); for (int i=0; i< originFiles.length; i++) { FileUtil.copyFileDeep(originFiles[i], destinationFiles[i]); Log.d(TAG, "Transferred " + originFiles[i] + " to " + destinationFiles[i]); } } catch(IOException e){ // if we catch an error, delete all the new files we've copied over for (File destinationFile : destinationFiles) { if(destinationFile.exists()){ FileUtil.deleteFileOrDir(destinationFile); } } } // Delete all the to be submitted files, we have them copied for transfer. for (File originFile : originFiles) { if(originFile.exists()){ FileUtil.deleteFileOrDir(originFile); } } } private void onZipSuccesful() { myStatusText.setText(localize("wifi.direct.zip.successful")); updateStatusText(); sendFiles(); } private void onZipError() { FileUtil.deleteFileOrDir(new File(toBeTransferredDirectory)); Log.d(CommCareWiFiDirectActivity.TAG, "Zip unsuccessful"); } private void onUnzipSuccessful(Integer result) { Logger.log(TAG, "Successfully unzipped " + result.toString() + " files."); myStatusText.setText(localize("wifi.direct.receive.successful", result.toString())); if (!FileUtil.deleteFileOrDir(new File(receiveDirectory))) { Log.d(TAG, "source zip not succesfully deleted"); } updateStatusText(); } private void onRecordPullCompleted(Pair<FormUploadResult, FormRecord[]> result, CommCareWiFiDirectActivity receiver) { myStatusText.setText(localize("wifi.direct.pull.successful")); if (result != null) { if (result.first != FormUploadResult.FULL_SUCCESS) { // if we had files but they failed, we should error and block receiver.myStatusText.setText(localize("wifi.direct.pull.unsuccessful", "Problem transferring forms to file system")); receiver.transplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); return; } this.cachedRecords = result.second; } updateStatusText(); moveReceivedFiles(); zipFiles(); } private void moveFormRecordsToFiles(){ Logger.log(TAG, "Getting records from storage"); FormRecordToFileTask formRecordToFileTask = new FormRecordToFileTask(this, toBeTransferredDirectory) { @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, Pair<FormUploadResult, FormRecord[]> result) { receiver.onRecordPullCompleted(result, receiver); } @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], taskId); receiver.myStatusText.setText(update[0]); } @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { receiver.myStatusText.setText(localize("wifi.direct.pull.unsuccessful", e.getMessage())); receiver.transplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); } }; formRecordToFileTask.connect(this); formRecordToFileTask.execute(); } private void zipFiles() { Logger.log(TAG, "Zipping Files"); ZipTask mZipTask = new ZipTask(toBeTransferredDirectory, zipFilePath) { @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], taskId); receiver.myStatusText.setText(update[0]); } @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { receiver.myStatusText.setText(localize("wifi.direct.zip.unsuccessful", e.getMessage())); receiver.transplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); } @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, ZipTaskResult result) { if (result == ZipTaskResult.Success) { receiver.onZipSuccesful(); } else { receiver.onZipError(); receiver.transplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); } } }; mZipTask.connect(CommCareWiFiDirectActivity.this); mZipTask.execute(); } private void sendFiles() { Logger.log(TAG, "Sending Files via Wi-fi Direct"); TextView statusText = myStatusText; statusText.setText(localize("wifi.direct.send.forms")); Log.d(CommCareWiFiDirectActivity.TAG, "Starting form transfer task"); final WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment)getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); String address = fragment.getHostAddress(); FormTransferTask mTransferTask = new FormTransferTask(address, zipFilePath, 8988) { @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, Boolean result) { if (result == Boolean.TRUE) { receiver.onSendSuccessful(); } else { receiver.onSendFail(); receiver.transplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); } } @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], taskId); receiver.myStatusText.setText(update[0]); } @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { receiver.myStatusText.setText(localize("wifi.direct.send.unsuccessful")); receiver.transplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); } }; mTransferTask.connect(CommCareWiFiDirectActivity.this); mTransferTask.execute(); Log.d(CommCareWiFiDirectActivity.TAG, "Task started"); } private void onSendSuccessful() { Logger.log(TAG, "File Send Successful"); Toast.makeText(CommCareWiFiDirectActivity.this, localize("wifi.direct.send.successful"), Toast.LENGTH_SHORT).show(); updateStatusText(); myStatusText.setText(localize("wifi.direct.send.successful")); this.cleanPostSend(); } private void onSendFail() { Logger.log(TAG, "Error Sending Files"); } private void updateStatusText() { SqlStorage<FormRecord> storage = CommCareApplication.instance().getUserStorage(FormRecord.class); Vector<Integer> ids = StorageUtils.getUnsentOrUnprocessedFormIdsForCurrentApp(storage); int numUnsyncedForms = ids.size(); int numUnsubmittedForms; File wDirectory = new File(toBeSubmittedDirectory); if (!wDirectory.exists() || !wDirectory.isDirectory()) { numUnsubmittedForms = 0; } else { numUnsubmittedForms = wDirectory.listFiles().length; } if (mState.equals(wdState.send)) { stateHeaderText.setText(localize("wifi.direct.status.transfer.header")); formCountText.setText(localize("wifi.direct.status.transfer.count", new String[] {"" + numUnsyncedForms, "" + numUnsubmittedForms})); stateStatusText.setText(localize("wifi.direct.status.transfer.message")); } else if (mState.equals(wdState.receive)) { stateHeaderText.setText(localize("wifi.direct.status.receive.header")); formCountText.setText(localize("wifi.direct.status.receive.count", "" + numUnsubmittedForms)); stateStatusText.setText(localize("wifi.direct.status.receive.message")); } else { stateHeaderText.setText(localize("wifi.direct.status.submit.header")); formCountText.setText(localize("wifi.direct.status.submit.count", "" + numUnsubmittedForms)); stateStatusText.setText(localize("wifi.direct.status.submit.message")); } } public static boolean copyFile(InputStream inputStream, OutputStream out) { Logger.log(TAG, "File server copying file"); Log.d(CommCareWiFiDirectActivity.TAG, "Copying file"); if (inputStream == null) { Log.d(CommCareWiFiDirectActivity.TAG, "Input Null"); } byte buf[] = new byte[1024]; int len; try { while ((len = inputStream.read(buf)) != -1) { Log.d(CommCareWiFiDirectActivity.TAG, "Copying file : " + new String(buf)); out.write(buf, 0, len); } out.close(); inputStream.close(); } catch (IOException e) { Log.d(CommCareWiFiDirectActivity.TAG, e.toString()); Logger.log(TAG, "Copy in File Server failed"); return false; } Logger.log(TAG, "Copy in File Server successful"); return true; } @Override public void onFormsCopied(String result) { Logger.log(TAG, "Copied files successfully"); Log.d(CommCareWiFiDirectActivity.TAG, "onCopySuccess"); this.unzipFiles(result); } @Override public void updatePeers() { Logger.log(TAG, "Wi-Fi direct peers updating"); mManager.requestPeers(mChannel, (PeerListListener)this.getSupportFragmentManager() .findFragmentById(R.id.frag_list)); } @Override public void updateDeviceStatus(WifiP2pDevice mDevice) { Logger.log(TAG, "Wi-fi direct status updating"); DeviceListFragment fragment = (DeviceListFragment)this.getSupportFragmentManager() .findFragmentById(R.id.frag_list); fragment.updateThisDevice(mDevice); } /** * Implementation of generateProgressDialog() for DialogController -- other methods * handled entirely in CommCareActivity */ @Override public CustomProgressDialog generateProgressDialog(int taskId) { String title, message; switch (taskId) { case ZipTask.ZIP_TASK_ID: title = localize("wifi.direct.zip.task.title").toString(); message = localize("wifi.direct.zip.task.message").toString(); break; case UnzipTask.UNZIP_TASK_ID: title = localize("wifi.direct.unzip.task.title").toString(); message = localize("wifi.direct.unzip.task.message").toString(); break; case SendTask.BULK_SEND_ID: title = localize("wifi.direct.submit.task.title").toString(); message = localize("wifi.direct.submit.task.message").toString(); break; case FormTransferTask.BULK_TRANSFER_ID: title = localize("wifi.direct.transfer.task.title").toString(); message = localize("wifi.direct.transfer.task.message").toString(); break; case FILE_SERVER_TASK_ID: title = localize("wifi.direct.receive.task.title").toString(); message = localize("wifi.direct.receive.task.message").toString(); break; case WipeTask.WIPE_TASK_ID: title = localize("wifi.direct.wipe.task.title").toString(); message = localize("wifi.direct.wipe.task.message").toString(); break; case FormRecordToFileTask.PULL_TASK_ID: title = localize("wifi.direct.pull.task.title").toString(); message = localize("wifi.direct.pull.task.message").toString(); break; default: Log.w(TAG, "taskId passed to generateProgressDialog does not match " + "any valid possibilities in CommCareWifiDirectActivity"); return null; } return CustomProgressDialog.newInstance(title, message, taskId); } public wdState getWifiDirectState() { return mState; } }