package org.commcare.dalvik.activities; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Vector; import org.commcare.android.database.SqlStorage; import org.commcare.android.database.user.models.FormRecord; import org.commcare.android.framework.CommCareActivity; import org.commcare.android.framework.DeviceDetailFragment; import org.commcare.android.framework.DeviceListFragment; import org.commcare.android.framework.DeviceListFragment.DeviceActionListener; import org.commcare.android.framework.FileServerFragment; import org.commcare.android.framework.FileServerFragment.FileServerListener; import org.commcare.android.framework.WiFiDirectManagementFragment; import org.commcare.android.framework.WiFiDirectManagementFragment.WifiDirectManagerListener; import org.commcare.android.tasks.FormTransferTask; import org.commcare.android.tasks.SendTask; import org.commcare.android.tasks.UnzipTask; import org.commcare.android.tasks.WipeTask; import org.commcare.android.tasks.ZipTask; import org.commcare.android.tasks.templates.CommCareTask; import org.commcare.android.util.FileUtil; import org.commcare.dalvik.R; import org.commcare.dalvik.application.CommCareApplication; import org.commcare.dalvik.dialogs.CustomProgressDialog; import org.commcare.dalvik.services.WiFiDirectBroadcastReceiver; import org.javarosa.core.services.Logger; import org.javarosa.core.services.locale.Localization; 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.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * 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 CommCareActivity<CommCareWiFiDirectActivity> implements DeviceActionListener, FileServerListener, WifiDirectManagerListener { public static final String TAG = "cc-wifidirect"; public static final String KEY_NUMBER_DUMPED ="wd_num_dumped"; public static final int UNZIP_TASK_ID = 392582; public WifiP2pManager mManager; public Channel mChannel; WiFiDirectBroadcastReceiver mReceiver; IntentFilter mIntentFilter; public enum wdState{send,receive,submit}; Button discoverButton; Button sendButton; Button submitButton; Button changeModeButton; public static String baseDirectory; public static String sourceDirectory; public static String sourceZipDirectory; public static String receiveDirectory; public static String receiveZipDirectory; public static String writeDirectory; public TextView myStatusText; public TextView formCountText; public TextView stateHeaderText; public TextView stateStatusText; public static final int FILE_SERVER_TASK_ID = 129123; public wdState mState = wdState.send; public FormRecord[] cachedRecords; /* * (non-Javadoc) * @see org.commcare.android.framework.CommCareActivity#onCreate(android.os.Bundle) */ @Override public 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 = FileUtil.getDumpDirectory(this); if(baseDir == null){ Toast.makeText(CommCareWiFiDirectActivity.this, "Wi-Fi Direct Requires an External SD Card", Toast.LENGTH_LONG).show(); this.setResult(RESULT_CANCELED); finish(); } baseDirectory = baseDir + "/" + Localization.get("wifi.direct.base.folder"); sourceDirectory = baseDirectory + "/source"; sourceZipDirectory = baseDirectory + "/zipSource.zip"; receiveDirectory = baseDirectory + "/receive"; receiveZipDirectory = receiveDirectory + "/zipDest"; writeDirectory = baseDirectory + "/write"; discoverButton = (Button)this.findViewById(R.id.discover_button); discoverButton.setOnClickListener(new OnClickListener(){ /* * (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { discoverPeers(); } }); sendButton = (Button)this.findViewById(R.id.send_button); sendButton.setOnClickListener(new OnClickListener(){ /* * (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { prepareFileTransfer(); } }); submitButton = (Button)this.findViewById(R.id.submit_button); submitButton.setOnClickListener(new OnClickListener(){ /* * (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { submitFiles(); } }); changeModeButton = (Button)this.findViewById(R.id.reset_state_button); changeModeButton.setOnClickListener(new OnClickListener(){ /* * (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { changeState(); } }); 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); showDialog(this, "Transfer, Receive, Submit?", "Do you want to transfer, receive, or submit forms?"); } /*register the broadcast receiver */ protected void onResume() { super.onResume(); Logger.log(TAG, "resuming wi-fi direct activity"); final WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment) getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, fragment); registerReceiver(mReceiver, mIntentFilter); fragment.startReceiver(mManager, mChannel, mReceiver); updateStatusText(); } /* * (non-Javadoc) * @see org.commcare.android.framework.CommCareActivity#onPause() * * unregister the broadcast receiver */ @Override protected void onPause() { super.onPause(); Logger.log(TAG, "Pausing wi-fi direct activity"); unregisterReceiver(mReceiver); } public 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, "WiFi Direct is Off - Turn it on, and press the \"Host\" button", Toast.LENGTH_SHORT).show(); //hostButton.setVisibility(View.VISIBLE); return; } mManager.createGroup(mChannel, fragment); } public void changeState(){ showDialog(this, "Send, Receive, Submit?", "Do you want to send, receive, or submit forms?"); } public void hostWiFiGroup(){ Logger.log(TAG, "creating wi-fi group"); WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment) getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); mManager.createGroup(mChannel, fragment); } public void showDialog(Activity activity, String title, CharSequence message) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); if (title != null) builder.setTitle(title); builder.setMessage(message); builder.setNeutralButton("Receive Forms", new DialogInterface.OnClickListener(){ /* * (non-Javadoc) * @see android.content.DialogInterface.OnClickListener#onClick(android.content.DialogInterface, int) */ @Override public void onClick(DialogInterface dialog, int which) { beReceiver(); }}); builder.setNegativeButton("Send Forms", new DialogInterface.OnClickListener(){ /* * (non-Javadoc) * @see android.content.DialogInterface.OnClickListener#onClick(android.content.DialogInterface, int) */ @Override public void onClick(DialogInterface dialog, int which) { beSender(); }}); builder.setPositiveButton("Submit Forms", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { beSubmitter(); }}); builder.show(); } public void beSender(){ myStatusText.setText("Entered 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; sendButton.setVisibility(View.VISIBLE); submitButton.setVisibility(View.GONE); discoverButton.setVisibility(View.VISIBLE); updateStatusText(); } public void beReceiver(){ myStatusText.setText("Entered 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; sendButton.setVisibility(View.GONE); updateStatusText(); discoverButton.setVisibility(View.GONE); submitButton.setVisibility(View.GONE); } public void beSubmitter(){ unzipFilesHelper(); Logger.log(TAG,"Device designated as submitter"); myStatusText.setText("Entered 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; updateStatusText(); discoverButton.setVisibility(View.GONE); sendButton.setVisibility(View.GONE); submitButton.setVisibility(View.VISIBLE); } public void cleanPostSend(){ Logger.log(TAG, "cleaning forms after successful Wi-fi direct transfer"); // remove Forms from CC WipeTask mWipeTask = new WipeTask(getApplicationContext(), CommCareApplication._().getCurrentApp().getCommCarePlatform(), this.cachedRecords){ /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverResult(java.lang.Object, java.lang.Object) */ @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, Boolean result) { receiver.onCleanSuccessful(); } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverUpdate(java.lang.Object, java.lang.Object[]) */ @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], WipeTask.WIPE_TASK_ID); receiver.myStatusText.setText(update[0]); } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverError(java.lang.Object, java.lang.Exception) */ @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { receiver.myStatusText.setText("Error wiping forms: " + e.getMessage()); receiver.TransplantStyle(myStatusText, R.layout.template_text_notification_problem); } }; mWipeTask.connect(CommCareWiFiDirectActivity.this); mWipeTask.execute(); FileUtil.deleteFile(new File(sourceDirectory)); FileUtil.deleteFile(new File(sourceZipDirectory)); this.cachedRecords = null; } protected 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 (writeDirectory); 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("Phone has received no forms via Wi-fi direct for Submitting; did you mean to Send forms?"); TransplantStyle(myStatusText, R.layout.template_text_notification_problem); return; } final int formsOnSD = files.length; //if there're no forms to dump, 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._().getCurrentApp().getAppPreferences(); SendTask<CommCareWiFiDirectActivity> mSendTask = new SendTask<CommCareWiFiDirectActivity>(getApplicationContext(), CommCareApplication._().getCurrentApp().getCommCarePlatform(), settings.getString("PostURL", url), receiveFolder){ /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverResult(java.lang.Object, java.lang.Object) */ @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, Boolean result) { if(result == Boolean.TRUE){ Intent i = new Intent(getIntent()); i.putExtra(KEY_NUMBER_DUMPED, formsOnSD); receiver.setResult(BULK_SEND_ID, i); receiver.finish(); return; } else { //assume that we've already set the error message, but make it look scary receiver.TransplantStyle(myStatusText, R.layout.template_text_notification_problem); } } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverUpdate(java.lang.Object, java.lang.Object[]) */ @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], BULK_SEND_ID); receiver.myStatusText.setText(update[0]); } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverError(java.lang.Object, java.lang.Exception) */ @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { Logger.log(TAG, "Error submitting forms in wi-fi direct"); 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(); } public 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("Zip file exists, unzipping..."); for(int i=0; i< zipDirContents.length; i++){ unzipFiles(zipDirContents[i].getAbsolutePath()); } return true; } public void unzipFiles(String fn){ Logger.log(TAG, "Unzipping files in Wi-fi direct"); Log.d(TAG, "creating unzip task"); UnzipTask<CommCareWiFiDirectActivity> mUnzipTask = new UnzipTask<CommCareWiFiDirectActivity>() { /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverResult(java.lang.Object, java.lang.Object) */ @Override protected void deliverResult( CommCareWiFiDirectActivity receiver, Integer result) { Log.d(TAG, "delivering unzip result"); if(result > 0){ receiver.onUnzipSuccessful(result); return; } else { //assume that we've already set the error message, but make it look scary receiver.TransplantStyle(myStatusText, R.layout.template_text_notification_problem); } } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverUpdate(java.lang.Object, java.lang.Object[]) */ @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]); } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverError(java.lang.Object, java.lang.Exception) */ @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); Log.d(TAG, "executing task with: " + fn + " , " + writeDirectory); mUnzipTask.execute(fn, writeDirectory); } /* 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"); Log.d(TAG, "discoverPeers"); WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment) getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); if(!fragment.isWifiP2pEnabled()){ Toast.makeText(CommCareWiFiDirectActivity.this, "WiFi Direct is Off", Toast.LENGTH_SHORT).show(); return; } final DeviceListFragment dlFragment = (DeviceListFragment) getSupportFragmentManager() .findFragmentById(R.id.frag_list); dlFragment.onInitiateDiscovery(); mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() { /* * (non-Javadoc) * @see android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess() */ @Override public void onSuccess() { Toast.makeText(CommCareWiFiDirectActivity.this, "Discovery Initiated", Toast.LENGTH_SHORT).show(); } /* * (non-Javadoc) * @see android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure(int) */ @Override public void onFailure(int reasonCode) { Logger.log(TAG, "Discovery of Wi-fi peers failed"); if(reasonCode == 0){ Toast.makeText(CommCareWiFiDirectActivity.this, "Discovery Failed likely due to bad Wi-fi; please retry", Toast.LENGTH_SHORT).show(); } else if(reasonCode == 2){ Toast.makeText(CommCareWiFiDirectActivity.this, "Discovery failed due to bad Wi-fi state; turn Wi-fi on and off, then retry", Toast.LENGTH_SHORT).show(); } else{ Toast.makeText(CommCareWiFiDirectActivity.this, "Discovery failed with reason code: " + reasonCode, Toast.LENGTH_SHORT).show(); } } }); } 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(); } } /* * (non-Javadoc) * @see org.commcare.android.framework.DeviceListFragment.DeviceActionListener#showDetails(android.net.wifi.p2p.WifiP2pDevice) */ @Override public void showDetails(WifiP2pDevice device) { Log.d(TAG, "showDetails"); DeviceDetailFragment fragment = (DeviceDetailFragment) getSupportFragmentManager() .findFragmentById(R.id.frag_detail); fragment.showDetails(device); } /* * (non-Javadoc) * @see org.commcare.android.framework.DeviceListFragment.DeviceActionListener#connect(android.net.wifi.p2p.WifiP2pConfig) */ @Override public void connect(WifiP2pConfig config) { Logger.log(TAG,"connecting to wi-fi peer"); Log.d(TAG, "connect in activity"); mManager.connect(mChannel, config, new ActionListener() { /* * (non-Javadoc) * @see android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess() */ @Override public void onSuccess() { // WiFiDirectBroadcastReceiver will notify us. Ignore for now. } /* * (non-Javadoc) * @see android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure(int) */ @Override public void onFailure(int reason) { Logger.log(TAG,"Connection to peer failed"); Toast.makeText(CommCareWiFiDirectActivity.this, "Connect failed. Retry.", Toast.LENGTH_SHORT).show(); } }); } /* * (non-Javadoc) * @see org.commcare.android.framework.DeviceListFragment.DeviceActionListener#disconnect() */ @Override public void disconnect() { Logger.log(TAG, "disconnecting from wi-fi direct group"); final DeviceDetailFragment fragment = (DeviceDetailFragment) getSupportFragmentManager() .findFragmentById(R.id.frag_detail); fragment.resetViews(); mManager.removeGroup(mChannel, new ActionListener() { /* * (non-Javadoc) * @see android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure(int) */ @Override public void onFailure(int reasonCode) { Log.d(TAG, "Disconnect failed. Reason :" + reasonCode); } /* * (non-Javadoc) * @see android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess() */ @Override public void onSuccess() { fragment.getView().setVisibility(View.GONE); } }); } /* * (non-Javadoc) * @see org.commcare.android.framework.DeviceListFragment.DeviceActionListener#cancelDisconnect() */ @Override public void cancelDisconnect() { /* * A cancel abort request by user. Disconnect i.e. removeGroup if * already connected. Else, request WifiP2pManager to abort the ongoing * request */ if (mManager != null) { final DeviceListFragment fragment = (DeviceListFragment) getSupportFragmentManager() .findFragmentById(R.id.frag_list); if (fragment.getDevice() == null || fragment.getDevice().status == WifiP2pDevice.CONNECTED) { disconnect(); } else if (fragment.getDevice().status == WifiP2pDevice.AVAILABLE || fragment.getDevice().status == WifiP2pDevice.INVITED) { mManager.cancelConnect(mChannel, new ActionListener() { /* * (non-Javadoc) * @see android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess() */ @Override public void onSuccess() { Toast.makeText(CommCareWiFiDirectActivity.this, "Aborting connection", Toast.LENGTH_SHORT).show(); } /* * (non-Javadoc) * @see android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure(int) */ @Override public void onFailure(int reasonCode) { Toast.makeText(CommCareWiFiDirectActivity.this, "Connect abort request failed. Reason Code: " + reasonCode, Toast.LENGTH_SHORT).show(); } }); } } } public 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(sourceZipDirectory); final WiFiDirectManagementFragment fragment = (WiFiDirectManagementFragment) getSupportFragmentManager() .findFragmentById(R.id.wifi_manager_fragment); if(!fragment.getDeviceConnected()){ Logger.log(TAG, "Device not connected to Wi-Fi Direct group"); myStatusText.setText("This devices is not connected to any Wi-Fi Direct group."); return; } zipFiles(); } public void onZipSuccesful(FormRecord[] records){ Logger.log(TAG, "successfully zipped files of size: " + records.length); Log.d(CommCareWiFiDirectActivity.TAG, "Zip successful, attempting to send"); myStatusText.setText("Zip successful, attempting to send files..."); this.cachedRecords = records; updateStatusText(); sendFiles(); } public void onZipError(){ FileUtil.deleteFile(new File(sourceDirectory)); Logger.log(TAG, "Error zipping files"); Log.d(CommCareWiFiDirectActivity.TAG, "Zip unsuccesful"); } public void onUnzipSuccessful(Integer result){ Logger.log(TAG, "Successfully unzipped files"); Toast.makeText(CommCareWiFiDirectActivity.this, "Received " + result.toString() + " Files Successfully!", Toast.LENGTH_SHORT).show(); myStatusText.setText("Receive Successful!"); if(!FileUtil.deleteFile(new File(receiveDirectory))){ Log.d(TAG, "source zip not succesfully deleted"); } updateStatusText(); } public void zipFiles(){ Logger.log(TAG, "Zipping Files"); Log.d(CommCareWiFiDirectActivity.TAG, "Zipping Files2"); ZipTask mZipTask = new ZipTask(this, CommCareApplication._().getCurrentApp().getCommCarePlatform()){ /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverUpdate(java.lang.Object, java.lang.Object[]) */ @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], taskId); receiver.myStatusText.setText(update[0]); } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverError(java.lang.Object, java.lang.Exception) */ @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { receiver.myStatusText.setText("Error zipping files"); receiver.TransplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverResult(java.lang.Object, java.lang.Object) */ @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, FormRecord[] result) { if(result != null){ receiver.onZipSuccesful(result); return; } else { receiver.onZipError(); receiver.TransplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); return; } } }; mZipTask.connect(CommCareWiFiDirectActivity.this); mZipTask.execute(); } public void sendFiles(){ Logger.log(TAG, "Sending Files via Wi-fi Direct"); TextView statusText = myStatusText; statusText.setText("Sending files..." ); 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,sourceZipDirectory,8988){ /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverResult(java.lang.Object, java.lang.Object) */ @Override protected void deliverResult(CommCareWiFiDirectActivity receiver, Boolean result) { if(result == Boolean.TRUE){ receiver.onSendSuccessful(); return; } else { receiver.onSendFail(); receiver.TransplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); return; } } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverUpdate(java.lang.Object, java.lang.Object[]) */ @Override protected void deliverUpdate(CommCareWiFiDirectActivity receiver, String... update) { receiver.updateProgress(update[0], taskId); receiver.myStatusText.setText(update[0]); } /* * (non-Javadoc) * @see org.commcare.android.tasks.templates.CommCareTask#deliverError(java.lang.Object, java.lang.Exception) */ @Override protected void deliverError(CommCareWiFiDirectActivity receiver, Exception e) { receiver.myStatusText.setText("Error sending files with exception: " + e.getMessage()); receiver.TransplantStyle(receiver.myStatusText, R.layout.template_text_notification_problem); } }; mTransferTask.connect(CommCareWiFiDirectActivity.this); mTransferTask.execute(); Log.d(CommCareWiFiDirectActivity.TAG, "Task started"); } public void onSendSuccessful(){ Logger.log(TAG, "File Send Successful"); Toast.makeText(CommCareWiFiDirectActivity.this, "File Send Successful!", Toast.LENGTH_SHORT).show(); updateStatusText(); myStatusText.setText("Forms Tranferred Successfully!"); this.cleanPostSend(); } public void onSendFail(){ Logger.log(TAG, "Error Sending Files"); } public void updateStatusText(){ SqlStorage<FormRecord> storage = CommCareApplication._().getUserStorage(FormRecord.class); //Get all forms which are either unsent or unprocessed Vector<Integer> ids = storage.getIDsForValues(new String[] {FormRecord.META_STATUS}, new Object[] {FormRecord.STATUS_UNSENT}); ids.addAll(storage.getIDsForValues(new String[] {FormRecord.META_STATUS}, new Object[] {FormRecord.STATUS_COMPLETE})); int numUnsyncedForms = ids.size(); int numUnsubmittedForms = 0; File wDirectory = new File(writeDirectory); if(!wDirectory.exists() || !wDirectory.isDirectory()){ numUnsubmittedForms = 0; } else{ numUnsubmittedForms = wDirectory.listFiles().length; } if(mState.equals(wdState.send)){ stateHeaderText.setText("You are in Transfer Form Mode"); formCountText.setText("Phone has " + numUnsyncedForms + " unsent forms."); stateStatusText.setText("You are in Transfer Form mode. This will allow you to transfer forms from this device to another device via Wi-Fi Direct."); } else if(mState.equals(wdState.receive)){ stateHeaderText.setText("You are in Receive Form Mode"); stateStatusText.setText("This will allow you to receive forms on this device from another device via Wi-Fi Direct"); formCountText.setText("SD Card has " + numUnsubmittedForms + " collected forms."); } else{ stateHeaderText.setText("You are in Submit Form Mode"); stateStatusText.setText("This mode will allow you to submit forms to the CommCare Server if you have an internet connection."); formCountText.setText("SD Card has " + numUnsubmittedForms + " unsubmitted forms."); } } 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; } /* * (non-Javadoc) * @see org.commcare.android.framework.FileServerFragment.FileServerListener#onFormsCopied(java.lang.String) */ @Override public void onFormsCopied(String result) { Logger.log(TAG, "Copied files successfully"); Log.d(CommCareWiFiDirectActivity.TAG, "onCopySuccess"); this.unzipFiles(result); } /* * (non-Javadoc) * @see org.commcare.android.framework.WiFiDirectManagementFragment.WifiDirectManagerListener#updatePeers() */ @Override public void updatePeers() { Logger.log(TAG, "Wi-Fi direct peers updating"); mManager.requestPeers(mChannel, (PeerListListener) this.getSupportFragmentManager() .findFragmentById(R.id.frag_list)); } /* * (non-Javadoc) * @see org.commcare.android.framework.WiFiDirectManagementFragment.WifiDirectManagerListener#updateDeviceStatus(android.net.wifi.p2p.WifiP2pDevice) */ @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); } /* * (non-Javadoc) * @see org.commcare.android.framework.CommCareActivity#generateProgressDialog(int) * * 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 = "Zipping Forms..."; message ="CommCare is compressing your data for transfer"; break; case UnzipTask.UNZIP_TASK_ID: title = "Unzipping forms"; message = "CommCare is decompressing your forms onto your SD card"; break; case SendTask.BULK_SEND_ID: title = "Submitting Forms"; message = "CommCare is submitting your forms to the server"; break; case FormTransferTask.BULK_TRANSFER_ID: title = "Sending Forms"; message = "CommCare is sending your forms to your peer"; break; case FILE_SERVER_TASK_ID: title = "Starting Receiving Files"; message = "CommCare is receiving files"; break; case WipeTask.WIPE_TASK_ID: title = "Wiping forms"; message = "Cleaning up after transfer"; break; default: System.out.println("WARNING: taskId passed to generateProgressDialog does not match " + "any valid possibilities in CommCareWifiDirectActivity"); return null; } CustomProgressDialog dialog = CustomProgressDialog.newInstance(title, message, taskId); return dialog; } }