diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/DeviceListFragment.java b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/DeviceListFragment.java index c611c7b0d..c1b629e24 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/DeviceListFragment.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/DeviceListFragment.java @@ -54,33 +54,33 @@ import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTra * * The starting point for the module is {@link LocalFileTransferActivity} */ -public class DeviceListFragment extends ListFragment - implements WifiP2pManager.PeerListListener, WifiP2pManager.ConnectionInfoListener { +public class DeviceListFragment extends ListFragment { + //implements WifiP2pManager.PeerListListener, WifiP2pManager.ConnectionInfoListener { public static final String TAG = "DeviceListFragment"; - public static int PEER_HANDSHAKE_PORT = 8009; - public static int FILE_TRANSFER_PORT = 8008; + /*public static int PEER_HANDSHAKE_PORT = 8009; + public static int FILE_TRANSFER_PORT = 8008;*/ private SharedPreferenceUtil sharedPreferenceUtil; private AlertDialogShower alertDialogShower; private LocalFileTransferActivity localFileTransferActivity; // Parent activity, starting point of the module - private TransferProgressFragment transferProgressFragment; + /*private TransferProgressFragment transferProgressFragment;*/ // Sibling fragment, for displaying transfer progress - // Views part of the DeviceListFragment + /*// Views part of the DeviceListFragment @BindView(R.id.text_view_device_name) TextView deviceName; @BindView(R.id.progress_bar_searching_peers) ProgressBar searchingPeersProgressBar; @BindView(android.R.id.list) ListView listViewPeerDevices; - @BindView(android.R.id.empty) TextView textViewPeerDevices; + @BindView(android.R.id.empty) TextView textViewPeerDevices;*/ private Unbinder unbinder; private boolean fileSender = false; // Whether file sending device or not private ArrayList fileUriList; // Uris of files to be shared, available only for the sender device - private int totalFilesForTransfer = -1; + /*private int totalFilesForTransfer = -1; private int filesSent = 0; // Count of number of files transferred until now private ArrayList filesToSend = new ArrayList<>(); @@ -97,7 +97,7 @@ public class DeviceListFragment extends ListFragment private PeerGroupHandshakeAsyncTask peerGroupHandshakeAsyncTask; private SenderDeviceAsyncTask senderDeviceAsyncTaskArray[]; - private ReceiverDeviceAsyncTask receiverDeviceAsyncTask; + private ReceiverDeviceAsyncTask receiverDeviceAsyncTask;*/ @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { @@ -105,10 +105,10 @@ public class DeviceListFragment extends ListFragment localFileTransferActivity = (LocalFileTransferActivity) getActivity(); // As DeviceListFragment extends ListFragment for the purpose of displaying list of peers - this.setListAdapter( - new WifiPeerListAdapter(localFileTransferActivity, R.layout.row_peer_device, peerDevices)); + /*this.setListAdapter( + new WifiPeerListAdapter(localFileTransferActivity, R.layout.row_peer_device, peerDevices));*/ - if (localFileTransferActivity.isFileSender()) { + /*if (localFileTransferActivity.isFileSender()) { fileSender = true; fileUriList = localFileTransferActivity.getFileUriArrayList(); totalFilesForTransfer = fileUriList.size(); @@ -118,7 +118,7 @@ public class DeviceListFragment extends ListFragment } displayTransferProgressFragment(); - } + }*/ } @Override @@ -138,7 +138,7 @@ public class DeviceListFragment extends ListFragment @Override public void onListItemClick(ListView l, View v, int position, long id) { - /* Connection can only be initiated by user of the sender device, & only when transfer has not been started */ + /* Connection can only be initiated by user of the sender device, & only when transfer has not been started *//* if (!isFileSender() || fileTransferStarted) { return; } @@ -151,27 +151,27 @@ public class DeviceListFragment extends ListFragment showToast(localFileTransferActivity, R.string.performing_handshake, Toast.LENGTH_LONG); return Unit.INSTANCE; } - }); + });*/ } - private void displayTransferProgressFragment() { + /*private void displayTransferProgressFragment() { transferProgressFragment = TransferProgressFragment.newInstance(filesToSend); FragmentManager fragmentManager = localFileTransferActivity.getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(R.id.container_fragment_transfer_progress, transferProgressFragment) .commit(); - } + }*/ - public void updateUserDevice(WifiP2pDevice device) { // Update UI with user device's details + /*public void updateUserDevice(WifiP2pDevice device) { // Update UI with user device's details this.userDevice = device; if (userDevice != null) { deviceName.setText(userDevice.deviceName); Log.d(TAG, getDeviceStatus(userDevice.status)); } - } + }*/ - public static String getDeviceStatus(int status) { + /*public static String getDeviceStatus(int status) { if (BuildConfig.DEBUG) Log.d(TAG, "Peer Status: " + status); switch (status) { @@ -189,9 +189,9 @@ public class DeviceListFragment extends ListFragment default: return "Unknown"; } - } + }*/ - /* From WifiP2pManager.PeerListListener callback-interface */ + /* From WifiP2pManager.PeerListListener callback-interface *//* @Override public void onPeersAvailable(WifiP2pDeviceList peers) { searchingPeersProgressBar.setVisibility(View.GONE); @@ -204,9 +204,9 @@ public class DeviceListFragment extends ListFragment if (peerDevices.size() == 0) { Log.d(LocalFileTransferActivity.TAG, "No devices found"); } - } + }*/ - public void clearPeers() { + /*public void clearPeers() { peerDevices.clear(); ((WifiPeerListAdapter) getListAdapter()).notifyDataSetChanged(); } @@ -231,10 +231,10 @@ public class DeviceListFragment extends ListFragment textViewPeerDevices.setVisibility(View.INVISIBLE); } - /* From WifiP2pManager.ConnectionInfoListener callback-interface */ + *//* From WifiP2pManager.ConnectionInfoListener callback-interface *//* @Override public void onConnectionInfoAvailable(WifiP2pInfo info) { - /* Devices have successfully connected, and 'info' holds information about the wifi p2p group formed */ + *//* Devices have successfully connected, and 'info' holds information about the wifi p2p group formed *//* groupInfo = info; // Start handshake between the devices peerGroupHandshakeAsyncTask = new PeerGroupHandshakeAsyncTask(this, groupInfo); @@ -283,7 +283,7 @@ public class DeviceListFragment extends ListFragment } } - /* Helper methods */ + *//* Helper methods *//* public WifiP2pDevice getUserDevice() { return userDevice; @@ -335,11 +335,11 @@ public class DeviceListFragment extends ListFragment return fileReceiverDeviceAddress; } - public static String getFileName(Uri fileUri) { + *//*public static String getFileName(Uri fileUri) { String fileUriString = fileUri.toString(); // Returns text after location of last slash in the file path return fileUriString.substring(fileUriString.lastIndexOf('/') + 1); - } + }*//* public static void copyToOutputStream(InputStream inputStream, OutputStream outputStream) throws IOException { @@ -354,7 +354,7 @@ public class DeviceListFragment extends ListFragment outputStream.close(); inputStream.close(); Log.d(LocalFileTransferActivity.TAG, "Both streams closed"); - } + }*/ public interface DeviceActionListener { void connect(@NonNull WifiP2pDevice peerDevice); diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/LocalFileTransferActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/LocalFileTransferActivity.java index 1b4af8ce7..54ee0d51c 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/LocalFileTransferActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/LocalFileTransferActivity.java @@ -11,6 +11,8 @@ import android.net.Uri; import android.net.wifi.WpsInfo; import android.net.wifi.p2p.WifiP2pConfig; import android.net.wifi.p2p.WifiP2pDevice; +import android.net.wifi.p2p.WifiP2pDeviceList; +import android.net.wifi.p2p.WifiP2pInfo; import android.net.wifi.p2p.WifiP2pManager; import android.os.Build; import android.os.Bundle; @@ -18,6 +20,10 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.widget.AdapterView; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -26,12 +32,19 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import butterknife.BindView; import butterknife.ButterKnife; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.util.List; import kotlin.Unit; import kotlin.jvm.functions.Function0; +import org.kiwix.kiwixmobile.BuildConfig; import org.kiwix.kiwixmobile.KiwixApplication; import org.kiwix.kiwixmobile.R; import org.kiwix.kiwixmobile.utils.AlertDialogShower; @@ -42,6 +55,8 @@ import java.util.ArrayList; import javax.inject.Inject; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.FileItem.FileStatus.TO_BE_SENT; + /** * Created by @Aditya-Sood as a part of GSoC 2019. * @@ -53,8 +68,7 @@ import javax.inject.Inject; * The module uses this activity along with {@link DeviceListFragment} to manage connection * and file transfer between the devices. */ -public class LocalFileTransferActivity extends AppCompatActivity { - //implements WifiP2pManager.ChannelListener, DeviceListFragment.DeviceActionListener { +public class LocalFileTransferActivity extends AppCompatActivity implements WifiP2pManager.PeerListListener, WifiP2pManager.ConnectionInfoListener { public static final String TAG = "LocalFileTransferActvty"; // Not a typo, 'Log' tags have a length upper limit of 25 characters @@ -63,29 +77,46 @@ public class LocalFileTransferActivity extends AppCompatActivity { private static final int PERMISSION_REQUEST_CODE_COARSE_LOCATION = 1; private static final int PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS = 2; + public static int PEER_HANDSHAKE_PORT = 8009; + public static int FILE_TRANSFER_PORT = 8008; + + private TransferProgressFragment transferProgressFragment; + @Inject SharedPreferenceUtil sharedPreferenceUtil; @Inject AlertDialogShower alertDialogShower; @BindView(R.id.toolbar_local_file_transfer) Toolbar actionBar; + // Views part of the DeviceListFragment + @BindView(R.id.text_view_device_name) TextView deviceName; + @BindView(R.id.progress_bar_searching_peers) ProgressBar searchingPeersProgressBar; + @BindView(R.id.list_peer_devices) ListView listViewPeerDevices; + @BindView(R.id.text_view_empty_peer_list) TextView textViewPeerDevices; private ArrayList fileUriArrayList; // For sender device, stores Uris of files to be transferred public Boolean fileSendingDevice = false;// Whether the device is the file sender or not - /* Variables related to the WiFi P2P API */ - /*private boolean wifiP2pEnabled = false; // Whether WiFi has been enabled or not - private boolean retryChannel = false; // Whether channel has retried connecting previously - - private WifiP2pManager manager; // Overall manager of Wifi p2p connections for the module - private WifiP2pManager.Channel channel; - // Connects the module to device's underlying Wifi p2p framework - - private final IntentFilter intentFilter = new IntentFilter(); - // For specifying broadcasts (of the P2P API) that the module needs to respond to - private BroadcastReceiver receiver = null; // For receiving the broadcasts given by above filter*/ - public WifiDirectManager wifiDirectManager; + private int totalFilesForTransfer = -1; + private int filesSent = 0; // Count of number of files transferred until now + private ArrayList filesToSend = new ArrayList<>(); + + private WifiP2pDevice userDevice; // Represents the device on which the app is running + private WifiP2pInfo groupInfo; + // Corresponds to the WiFi P2P group formed between the two devices + private List peerDevices = new ArrayList(); + + private WifiP2pDevice selectedPeerDevice = null; + private InetAddress selectedPeerDeviceInetAddress; + + private InetAddress fileReceiverDeviceAddress; // IP address of the file receiving device + private boolean fileTransferStarted = false; + + private PeerGroupHandshakeAsyncTask peerGroupHandshakeAsyncTask; + private SenderDeviceAsyncTask senderDeviceAsyncTaskArray[]; + private ReceiverDeviceAsyncTask receiverDeviceAsyncTask; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -120,18 +151,39 @@ public class LocalFileTransferActivity extends AppCompatActivity { /* Initialisations for using the WiFi P2P API */ -/* - // Intents that the broadcast receiver will be responding to - intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); - intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); - intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); - intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); - - manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); - channel = manager.initialize(this, getMainLooper(), null);*/ - this.wifiDirectManager = new WifiDirectManager(this); wifiDirectManager.initialiseWifiDirectManager(); + + listViewPeerDevices.setAdapter(new WifiPeerListAdapter(this, R.layout.row_peer_device, peerDevices)); + + if(isFileSender()) { + totalFilesForTransfer = fileUriArrayList.size(); + + for (int i = 0; i < fileUriArrayList.size(); i++) { + filesToSend.add(new FileItem(getFileName(fileUriArrayList.get(i)), TO_BE_SENT)); + } + + displayTransferProgressFragment(); + + listViewPeerDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override public void onItemClick(AdapterView parent, View view, int position, long id) { + /* Connection can only be initiated by user of the sender device, & only when transfer has not been started */ + if (!isFileSender() || fileTransferStarted) { + return; + } + + selectedPeerDevice = (WifiP2pDevice) listViewPeerDevices.getAdapter().getItem(position); + alertDialogShower.show(new KiwixDialog.FileTransferConfirmation(selectedPeerDevice), + new Function0() { + @Override public Unit invoke() { + ((DeviceListFragment.DeviceActionListener) wifiDirectManager).connect(selectedPeerDevice); + showToast(LocalFileTransferActivity.this, R.string.performing_handshake, Toast.LENGTH_LONG); + return Unit.INSTANCE; + } + }); + } + }); + } } @Override @@ -160,11 +212,12 @@ public class LocalFileTransferActivity extends AppCompatActivity { return true; } - final DeviceListFragment deviceListFragment = + onInitiateDiscovery(); + /*final DeviceListFragment deviceListFragment = (DeviceListFragment) getSupportFragmentManager().findFragmentById( R.id.fragment_device_list); deviceListFragment.onInitiateDiscovery(); - deviceListFragment.performFieldInjection(sharedPreferenceUtil, alertDialogShower); + deviceListFragment.performFieldInjection(sharedPreferenceUtil, alertDialogShower);*/ /*manager.discoverPeers(channel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { @@ -225,21 +278,23 @@ public class LocalFileTransferActivity extends AppCompatActivity { } public void resetPeers() { - DeviceListFragment deviceListFragment = + /*DeviceListFragment deviceListFragment = (DeviceListFragment) getSupportFragmentManager().findFragmentById( R.id.fragment_device_list); if (deviceListFragment != null) { deviceListFragment.clearPeers(); - } + }*/ + clearPeers(); } public void resetData() { - DeviceListFragment deviceListFragment = + /*DeviceListFragment deviceListFragment = (DeviceListFragment) getSupportFragmentManager().findFragmentById( R.id.fragment_device_list); if (deviceListFragment != null) { deviceListFragment.clearPeers(); - } + }*/ + clearPeers(); } static void showToast(Context context, int stringResource, int duration) { @@ -484,12 +539,7 @@ public class LocalFileTransferActivity extends AppCompatActivity { @Override protected void onDestroy() { super.onDestroy(); - final DeviceListFragment deviceListFragment = - (DeviceListFragment) getSupportFragmentManager().findFragmentById( - R.id.fragment_device_list); - if (deviceListFragment != null) { - deviceListFragment.cancelAsyncTasks(); - } + cancelAsyncTasks(); } @Override @@ -497,4 +547,208 @@ public class LocalFileTransferActivity extends AppCompatActivity { super.onBackPressed(); wifiDirectManager.closeLocalFileTransferActivity(); } + + public static String getFileName(Uri fileUri) { + String fileUriString = fileUri.toString(); + // Returns text after location of last slash in the file path + return fileUriString.substring(fileUriString.lastIndexOf('/') + 1); + } + + private void displayTransferProgressFragment() { + transferProgressFragment = TransferProgressFragment.newInstance(filesToSend); + FragmentManager fragmentManager = this.getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.add(R.id.container_fragment_transfer_progress, transferProgressFragment) + .commit(); + } + + public void updateUserDevice(WifiP2pDevice device) { // Update UI with user device's details + this.userDevice = device; + + if (userDevice != null) { + deviceName.setText(userDevice.deviceName); + Log.d(TAG, getDeviceStatus(userDevice.status)); + } + } + + public static String getDeviceStatus(int status) { + + if (BuildConfig.DEBUG) Log.d(TAG, "Peer Status: " + status); + switch (status) { + case WifiP2pDevice.AVAILABLE: + return "Available"; + case WifiP2pDevice.INVITED: + return "Invited"; + case WifiP2pDevice.CONNECTED: + return "Connected"; + case WifiP2pDevice.FAILED: + return "Failed"; + case WifiP2pDevice.UNAVAILABLE: + return "Unavailable"; + + default: + return "Unknown"; + } + } + + /* From WifiP2pManager.PeerListListener callback-interface */ + @Override + public void onPeersAvailable(WifiP2pDeviceList peers) { + searchingPeersProgressBar.setVisibility(View.GONE); + listViewPeerDevices.setVisibility(View.VISIBLE); + + peerDevices.clear(); + peerDevices.addAll(peers.getDeviceList()); + ((WifiPeerListAdapter) listViewPeerDevices.getAdapter()).notifyDataSetChanged(); + + if (peerDevices.size() == 0) { + Log.d(LocalFileTransferActivity.TAG, "No devices found"); + } + } + + public void clearPeers() { + peerDevices.clear(); + ((WifiPeerListAdapter) listViewPeerDevices.getAdapter()).notifyDataSetChanged(); + } + + void cancelAsyncTasks() { + if (peerGroupHandshakeAsyncTask != null) { + peerGroupHandshakeAsyncTask.cancel(true); + } + + if (senderDeviceAsyncTaskArray != null) { + for (SenderDeviceAsyncTask task : senderDeviceAsyncTaskArray) { + task.cancel(true); + } + } else if (receiverDeviceAsyncTask != null) { + receiverDeviceAsyncTask.cancel(true); + } + } + + public void onInitiateDiscovery() { // Setup UI for searching peers + searchingPeersProgressBar.setVisibility(View.VISIBLE); + listViewPeerDevices.setVisibility(View.INVISIBLE); + textViewPeerDevices.setVisibility(View.INVISIBLE); + } + + /* From WifiP2pManager.ConnectionInfoListener callback-interface */ + @Override + public void onConnectionInfoAvailable(WifiP2pInfo info) { + /* Devices have successfully connected, and 'info' holds information about the wifi p2p group formed */ + groupInfo = info; + // Start handshake between the devices + peerGroupHandshakeAsyncTask = new PeerGroupHandshakeAsyncTask(this, groupInfo); + peerGroupHandshakeAsyncTask.execute(); + } + + public void setClientAddress(InetAddress clientAddress) { + if (clientAddress == null) { + // null is returned only in case of a failed handshake + showToast(this, R.string.device_not_cooperating, Toast.LENGTH_LONG); + wifiDirectManager.closeLocalFileTransferActivity(); + return; + } + + // If control reaches here, means handshake was successful + selectedPeerDeviceInetAddress = clientAddress; + startFileTransfer(); + } + + private void startFileTransfer() { + fileTransferStarted = true; + + if (groupInfo.groupFormed && !isFileSender()) { + displayTransferProgressFragment(); + + receiverDeviceAsyncTask = new ReceiverDeviceAsyncTask(this, transferProgressFragment); + receiverDeviceAsyncTask.execute(); + } else if (groupInfo.groupFormed) { + { + Log.d(LocalFileTransferActivity.TAG, "Starting file transfer"); + + fileReceiverDeviceAddress = + (groupInfo.isGroupOwner) ? selectedPeerDeviceInetAddress : groupInfo.groupOwnerAddress; + + // Hack for allowing slower receiver devices to setup server before sender device requests to connect + showToast(this, R.string.preparing_files, Toast.LENGTH_LONG); + for (int i = 0; i < 20000000; i++) ; + + senderDeviceAsyncTaskArray = new SenderDeviceAsyncTask[totalFilesForTransfer]; + for (int i = 0; i < totalFilesForTransfer; i++) { + senderDeviceAsyncTaskArray[i] = + new SenderDeviceAsyncTask(this, transferProgressFragment, i); + senderDeviceAsyncTaskArray[i].execute(fileUriArrayList.get(i)); + } + } + } + } + + /* Helper methods */ + + public WifiP2pDevice getUserDevice() { + return userDevice; + } + + public int getTotalFilesForTransfer() { + return totalFilesForTransfer; + } + + public void setTotalFilesForTransfer(int totalFilesForTransfer) { + this.totalFilesForTransfer = totalFilesForTransfer; + } + + public ArrayList getFileItems() { + return filesToSend; + } + + public void setFileItems(ArrayList fileItems) { + this.filesToSend = fileItems; + } + + public ArrayList getFileUriList() { + return fileUriArrayList; + } + + public void incrementTotalFilesSent() { + this.filesSent++; + } + + public boolean allFilesSent() { + return (filesSent == totalFilesForTransfer); + } + + /*public void performFieldInjection(SharedPreferenceUtil sharedPreferenceUtil, + AlertDialogShower alertDialogShower) { + this.sharedPreferenceUtil = sharedPreferenceUtil; + this.alertDialogShower = alertDialogShower; + }*/ + + public String getZimStorageRootPath() { + return (sharedPreferenceUtil.getPrefStorage() + "/Kiwix/"); + } + + public InetAddress getFileReceiverDeviceAddress() { + return fileReceiverDeviceAddress; + } + + /*public static String getFileName(Uri fileUri) { + String fileUriString = fileUri.toString(); + // Returns text after location of last slash in the file path + return fileUriString.substring(fileUriString.lastIndexOf('/') + 1); + }*/ + + public static void copyToOutputStream(InputStream inputStream, OutputStream outputStream) + throws IOException { + byte[] bufferForBytes = new byte[1024]; + int bytesRead; + + Log.d(TAG, "Copying to OutputStream..."); + while ((bytesRead = inputStream.read(bufferForBytes)) != -1) { + outputStream.write(bufferForBytes, 0, bytesRead); + } + + outputStream.close(); + inputStream.close(); + Log.d(LocalFileTransferActivity.TAG, "Both streams closed"); + } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/PeerGroupHandshakeAsyncTask.java b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/PeerGroupHandshakeAsyncTask.java index 25d9e35df..6e0fd1e14 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/PeerGroupHandshakeAsyncTask.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/PeerGroupHandshakeAsyncTask.java @@ -17,9 +17,9 @@ import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; -import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.DeviceListFragment.PEER_HANDSHAKE_PORT; -import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.DeviceListFragment.getFileName; import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.FileItem.FileStatus.TO_BE_SENT; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.PEER_HANDSHAKE_PORT; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.getFileName; /** * Helper class for the local file sharing module, used in {@link DeviceListFragment}. @@ -39,11 +39,11 @@ class PeerGroupHandshakeAsyncTask extends AsyncTask { private static final String TAG = "PeerGrpHndshakeAsyncTsk"; private final String HANDSHAKE_MESSAGE = "Request Kiwix File Sharing"; - private DeviceListFragment deviceListFragment; + private LocalFileTransferActivity localFileTransferActivity; private WifiP2pInfo groupInfo; - public PeerGroupHandshakeAsyncTask(DeviceListFragment deviceListFragment, WifiP2pInfo groupInfo) { - this.deviceListFragment = deviceListFragment; + public PeerGroupHandshakeAsyncTask(LocalFileTransferActivity localFileTransferActivity, WifiP2pInfo groupInfo) { + this.localFileTransferActivity = localFileTransferActivity; this.groupInfo = groupInfo; } @@ -100,12 +100,12 @@ class PeerGroupHandshakeAsyncTask extends AsyncTask { } private void exchangeFileTransferMetadata(OutputStream outputStream, InputStream inputStream) { - if (deviceListFragment.isFileSender()) { + if (localFileTransferActivity.isFileSender()) { try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) { // Send total number of files which will be transferred - objectOutputStream.writeObject("" + deviceListFragment.getTotalFilesForTransfer()); + objectOutputStream.writeObject("" + localFileTransferActivity.getTotalFilesForTransfer()); - ArrayList fileUriList = deviceListFragment.getFileUriList(); + ArrayList fileUriList = localFileTransferActivity.getFileUriList(); for ( Uri fileUri : fileUriList) { // Send the names of each of those files, in order objectOutputStream.writeObject(getFileName(fileUri)); @@ -120,7 +120,7 @@ class PeerGroupHandshakeAsyncTask extends AsyncTask { if (totalFilesObject.getClass().equals(String.class)) { int total = Integer.parseInt((String) totalFilesObject); - deviceListFragment.setTotalFilesForTransfer(total); + localFileTransferActivity.setTotalFilesForTransfer(total); ArrayList fileItems = new ArrayList<>(); for (int i = 0; i < total; i++) { // Read names of each of those files, in order @@ -131,7 +131,7 @@ class PeerGroupHandshakeAsyncTask extends AsyncTask { } } - deviceListFragment.setFileItems(fileItems); + localFileTransferActivity.setFileItems(fileItems); } } catch (Exception e) { e.printStackTrace(); @@ -145,6 +145,6 @@ class PeerGroupHandshakeAsyncTask extends AsyncTask { @Override protected void onPostExecute(InetAddress inetAddress) { - deviceListFragment.setClientAddress(inetAddress); + localFileTransferActivity.setClientAddress(inetAddress); } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/ReceiverDeviceAsyncTask.java b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/ReceiverDeviceAsyncTask.java index cf49db8e1..de6e5d230 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/ReceiverDeviceAsyncTask.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/ReceiverDeviceAsyncTask.java @@ -14,10 +14,10 @@ import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; -import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.DeviceListFragment.FILE_TRANSFER_PORT; -import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.DeviceListFragment.copyToOutputStream; import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.FileItem.FileStatus.SENDING; import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.FileItem.FileStatus.SENT; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.FILE_TRANSFER_PORT; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.copyToOutputStream; import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.showToast; /** @@ -34,13 +34,13 @@ class ReceiverDeviceAsyncTask extends AsyncTask { private static final String TAG = "ReceiverDeviceAsyncTask"; - private DeviceListFragment deviceListFragment; + private LocalFileTransferActivity localFileTransferActivity; private TransferProgressFragment transferProgressFragment; private int fileItemIndex; - public ReceiverDeviceAsyncTask(DeviceListFragment deviceListFragment, + public ReceiverDeviceAsyncTask(LocalFileTransferActivity localFileTransferActivity, TransferProgressFragment transferProgressFragment) { - this.deviceListFragment = deviceListFragment; + this.localFileTransferActivity = localFileTransferActivity; this.transferProgressFragment = transferProgressFragment; } @@ -49,9 +49,9 @@ class ReceiverDeviceAsyncTask extends AsyncTask { try (ServerSocket serverSocket = new ServerSocket(FILE_TRANSFER_PORT)) { if (BuildConfig.DEBUG) Log.d(TAG, "Server: Socket opened at " + FILE_TRANSFER_PORT); - final String KIWIX_ROOT = deviceListFragment.getZimStorageRootPath(); + final String KIWIX_ROOT = localFileTransferActivity.getZimStorageRootPath(); - int totalFileCount = deviceListFragment.getTotalFilesForTransfer(); + int totalFileCount = localFileTransferActivity.getTotalFilesForTransfer(); for (int currentFile = 1; currentFile <= totalFileCount && !isCancelled(); currentFile++) { Socket client = serverSocket.accept(); @@ -60,7 +60,7 @@ class ReceiverDeviceAsyncTask extends AsyncTask { fileItemIndex = currentFile - 1; publishProgress(SENDING); - ArrayList fileItems = deviceListFragment.getFileItems(); + ArrayList fileItems = localFileTransferActivity.getFileItems(); String incomingFileName = fileItems.get(fileItemIndex).getFileName(); final File clientNoteFileLocation = new File(KIWIX_ROOT + incomingFileName); @@ -76,7 +76,7 @@ class ReceiverDeviceAsyncTask extends AsyncTask { copyToOutputStream(client.getInputStream(), new FileOutputStream(clientNoteFileLocation)); publishProgress(SENT); - deviceListFragment.incrementTotalFilesSent(); + localFileTransferActivity.incrementTotalFilesSent(); } if (isCancelled()) { @@ -105,13 +105,13 @@ class ReceiverDeviceAsyncTask extends AsyncTask { if (BuildConfig.DEBUG) Log.d(TAG, "File transfer complete"); if (allFilesReceived) { - showToast(deviceListFragment.getActivity(), R.string.file_transfer_complete, + showToast(localFileTransferActivity, R.string.file_transfer_complete, Toast.LENGTH_LONG); } else { - showToast(deviceListFragment.getActivity(), R.string.error_during_transfer, + showToast(localFileTransferActivity, R.string.error_during_transfer, Toast.LENGTH_LONG); } - ((LocalFileTransferActivity) deviceListFragment.getActivity()).wifiDirectManager.closeLocalFileTransferActivity(); + (localFileTransferActivity).wifiDirectManager.closeLocalFileTransferActivity(); } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/SenderDeviceAsyncTask.java b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/SenderDeviceAsyncTask.java index 9c4e7c391..83ee0a91a 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/SenderDeviceAsyncTask.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/SenderDeviceAsyncTask.java @@ -16,9 +16,10 @@ import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; -import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.DeviceListFragment.FILE_TRANSFER_PORT; -import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.DeviceListFragment.getFileName; import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.FileItem.FileStatus.*; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.FILE_TRANSFER_PORT; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.copyToOutputStream; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.getFileName; import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.showToast; /** @@ -37,13 +38,13 @@ class SenderDeviceAsyncTask extends AsyncTask { private static final String TAG = "SenderDeviceAsyncTask"; - private DeviceListFragment deviceListFragment; + private LocalFileTransferActivity localFileTransferActivity; private TransferProgressFragment transferProgressFragment; private int fileItemIndex; - public SenderDeviceAsyncTask(DeviceListFragment deviceListFragment, + public SenderDeviceAsyncTask(LocalFileTransferActivity localFileTransferActivity, TransferProgressFragment transferProgressFragment, int fileItemIndex) { - this.deviceListFragment = deviceListFragment; + this.localFileTransferActivity = localFileTransferActivity; this.transferProgressFragment = transferProgressFragment; this.fileItemIndex = fileItemIndex; } @@ -56,7 +57,7 @@ class SenderDeviceAsyncTask extends AsyncTask { @Override protected Boolean doInBackground(Uri... fileUris) { Uri fileUri = fileUris[0]; // Uri of file to be transferred - ContentResolver contentResolver = deviceListFragment.getActivity().getContentResolver(); + ContentResolver contentResolver = localFileTransferActivity.getContentResolver(); try (Socket socket = new Socket(); InputStream fileInputStream = contentResolver.openInputStream( @@ -67,14 +68,14 @@ class SenderDeviceAsyncTask extends AsyncTask { } socket.bind(null); - String hostAddress = deviceListFragment.getFileReceiverDeviceAddress().getHostAddress(); + String hostAddress = localFileTransferActivity.getFileReceiverDeviceAddress().getHostAddress(); socket.connect((new InetSocketAddress(hostAddress, FILE_TRANSFER_PORT)), 15000); if (BuildConfig.DEBUG) Log.d(TAG, "Sender socket - " + socket.isConnected()); OutputStream socketOutputStream = socket.getOutputStream(); - DeviceListFragment.copyToOutputStream(fileInputStream, socketOutputStream); + copyToOutputStream(fileInputStream, socketOutputStream); if (BuildConfig.DEBUG) Log.d(TAG, "Sender: Data written"); return true; @@ -90,21 +91,20 @@ class SenderDeviceAsyncTask extends AsyncTask { @Override protected void onPostExecute(Boolean fileSendSuccessful) { - deviceListFragment.incrementTotalFilesSent(); + localFileTransferActivity.incrementTotalFilesSent(); if (fileSendSuccessful) { // Whether this task was successful in sending the file transferProgressFragment.changeStatus(fileItemIndex, SENT); } else { - Activity activity = deviceListFragment.getActivity(); - showToast(activity, activity.getString(R.string.error_sending, - getFileName(deviceListFragment.getFileUriList().get(fileItemIndex))), Toast.LENGTH_SHORT); + showToast(localFileTransferActivity, localFileTransferActivity.getString(R.string.error_sending, + getFileName(localFileTransferActivity.getFileUriList().get(fileItemIndex))), Toast.LENGTH_SHORT); transferProgressFragment.changeStatus(fileItemIndex, ERROR); } - if (deviceListFragment.allFilesSent()) { - showToast(deviceListFragment.getActivity(), R.string.file_transfer_complete, + if (localFileTransferActivity.allFilesSent()) { + showToast(localFileTransferActivity, R.string.file_transfer_complete, Toast.LENGTH_SHORT); - deviceListFragment.getActivity().finish(); + localFileTransferActivity.finish(); } } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiDirectBroadcastReceiver.java b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiDirectBroadcastReceiver.java index 9fc3bf4ba..cc9f36dab 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiDirectBroadcastReceiver.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiDirectBroadcastReceiver.java @@ -54,9 +54,7 @@ public class WifiDirectBroadcastReceiver extends BroadcastReceiver { if (manager != null) { /* List of available peers has changed, so request & use the new list through * PeerListListener.requestPeers() callback */ - manager.requestPeers(channel, - (WifiP2pManager.PeerListListener) wifiActivity.getSupportFragmentManager() - .findFragmentById(R.id.fragment_device_list)); + manager.requestPeers(channel, wifiActivity); } Log.d(LocalFileTransferActivity.TAG, "P2P peers changed"); } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { @@ -68,19 +66,14 @@ public class WifiDirectBroadcastReceiver extends BroadcastReceiver { if (networkInfo.isConnected()) { // Request connection info about the wifi p2p group formed upon connection - manager.requestConnectionInfo(channel, - (DeviceListFragment) wifiActivity.getSupportFragmentManager() - .findFragmentById(R.id.fragment_device_list)); + manager.requestConnectionInfo(channel, wifiActivity); } else { // Not connected after connection change -> Disconnected wifiActivity.resetData(); } } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) { // Update UI with wifi-direct details about the user device - DeviceListFragment deviceListFragment = - (DeviceListFragment) wifiActivity.getSupportFragmentManager() - .findFragmentById(R.id.fragment_device_list); - deviceListFragment.updateUserDevice( + wifiActivity.updateUserDevice( intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE)); } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiDirectManager.java b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiDirectManager.java index b5e37c85f..b7b848760 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiDirectManager.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiDirectManager.java @@ -16,11 +16,15 @@ import org.kiwix.kiwixmobile.R; import static android.os.Looper.getMainLooper; import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.showToast; + +/** + * Manager for the Wifi-P2p API, used in the local file transfer module + * */ public class WifiDirectManager implements WifiP2pManager.ChannelListener, DeviceListFragment.DeviceActionListener { private static final String TAG = "WifiDirectManager"; - LocalFileTransferActivity activity; + private LocalFileTransferActivity activity; /* Variables related to the WiFi P2P API */ private boolean wifiP2pEnabled = false; // Whether WiFi has been enabled or not @@ -125,12 +129,7 @@ public class WifiDirectManager implements WifiP2pManager.ChannelListener, Device @Override public void closeLocalFileTransferActivity() { - final DeviceListFragment deviceListFragment = - (DeviceListFragment) activity.getSupportFragmentManager().findFragmentById( - R.id.fragment_device_list); - if (deviceListFragment != null) { - deviceListFragment.cancelAsyncTasks(); - } + activity.cancelAsyncTasks(); activity.fileSendingDevice = false; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiPeerListAdapter.java b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiPeerListAdapter.java index 9d33dafe9..6e869f4c3 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiPeerListAdapter.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/local_file_transfer/WifiPeerListAdapter.java @@ -17,8 +17,8 @@ import org.kiwix.kiwixmobile.R; import java.util.List; -import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.DeviceListFragment.getDeviceStatus; import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.DeviceListFragment.TAG; +import static org.kiwix.kiwixmobile.zim_manager.local_file_transfer.LocalFileTransferActivity.getDeviceStatus; /** * Helper class, part of the local file sharing module. diff --git a/app/src/main/res/layout/activity_local_file_transfer.xml b/app/src/main/res/layout/activity_local_file_transfer.xml index cc50bab94..e27912ff3 100644 --- a/app/src/main/res/layout/activity_local_file_transfer.xml +++ b/app/src/main/res/layout/activity_local_file_transfer.xml @@ -14,20 +14,117 @@ android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent" - app:layout_constraintBottom_toTopOf="@id/fragment_device_list"> + app:layout_constraintRight_toRightOf="parent"> + app:title="@string/local_zim_sharing"> - + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_device_list.xml b/app/src/main/res/layout/fragment_device_list.xml index 5c0ff7007..798eee589 100644 --- a/app/src/main/res/layout/fragment_device_list.xml +++ b/app/src/main/res/layout/fragment_device_list.xml @@ -5,7 +5,7 @@ android:background="@android:color/transparent" xmlns:app="http://schemas.android.com/apk/res-auto"> - + android:visibility="gone"/>--> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 11a4ca5db..b829fdefd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -286,4 +286,5 @@ FILES FOR TRANSFER Preparing files for transfer.... Performing handshake.... + Local ZIM Sharing