mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-16 19:05:27 -04:00
*LocalFileTransferActivity_toKotlin*
This commit is contained in:
parent
10fb1d034d
commit
6f90e8455e
@ -1,406 +0,0 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.kiwix.kiwixmobile.local_file_transfer;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.p2p.WifiP2pDevice;
|
||||
import android.net.wifi.p2p.WifiP2pDeviceList;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.kiwix.kiwixmobile.ActivityExtensionsKt;
|
||||
import org.kiwix.kiwixmobile.R;
|
||||
import org.kiwix.kiwixmobile.core.base.BaseActivity;
|
||||
import org.kiwix.kiwixmobile.core.di.components.CoreComponent;
|
||||
import org.kiwix.kiwixmobile.core.utils.AlertDialogShower;
|
||||
import org.kiwix.kiwixmobile.core.utils.KiwixDialog;
|
||||
import org.kiwix.kiwixmobile.local_file_transfer.adapter.WifiP2pDelegate;
|
||||
import org.kiwix.kiwixmobile.local_file_transfer.adapter.WifiPeerListAdapter;
|
||||
|
||||
/**
|
||||
* Created by @Aditya-Sood as a part of GSoC 2019.
|
||||
*
|
||||
* This activity is the starting point for the module used for sharing zims between devices.
|
||||
*
|
||||
* The module is used for transferring ZIM files from one device to another, from within the
|
||||
* app. Two devices are connected to each other using WiFi Direct, followed by file transfer.
|
||||
*
|
||||
* File transfer involves two phases:
|
||||
* 1) Handshake with the selected peer device, using {@link PeerGroupHandshakeAsyncTask}
|
||||
* 2) After handshake, starting the files transfer using {@link SenderDeviceAsyncTask} on the sender
|
||||
* device and {@link ReceiverDeviceAsyncTask} files receiving device
|
||||
*/
|
||||
@SuppressLint("GoogleAppIndexingApiWarning")
|
||||
public class LocalFileTransferActivity extends BaseActivity implements
|
||||
WifiDirectManager.Callbacks {
|
||||
|
||||
// Not a typo, 'Log' tags have a length upper limit of 25 characters
|
||||
public static final String TAG = "LocalFileTransferActvty";
|
||||
public static final int REQUEST_ENABLE_LOCATION_SERVICES = 1;
|
||||
private static final int PERMISSION_REQUEST_CODE_COARSE_LOCATION = 1;
|
||||
private static final int PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS = 2;
|
||||
|
||||
@Inject AlertDialogShower alertDialogShower;
|
||||
@Inject WifiDirectManager wifiDirectManager;
|
||||
@Inject LocationManager locationManager;
|
||||
|
||||
@BindView(R.id.toolbar) Toolbar actionBar;
|
||||
@BindView(R.id.text_view_device_name) TextView deviceName;
|
||||
@BindView(R.id.progress_bar_searching_peers) ProgressBar searchingPeersProgressBar;
|
||||
@BindView(R.id.list_peer_devices) RecyclerView peerDeviceList;
|
||||
@BindView(R.id.text_view_empty_peer_list) TextView textViewPeerDevices;
|
||||
@BindView(R.id.recycler_view_transfer_files) RecyclerView filesRecyclerView;
|
||||
|
||||
private boolean isFileSender = false; // Whether the device is the file sender or not
|
||||
|
||||
private ArrayList<FileItem> filesForTransfer = new ArrayList<>();
|
||||
private FileListAdapter fileListAdapter;
|
||||
|
||||
private WifiPeerListAdapter wifiPeerListAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_local_file_transfer);
|
||||
/*
|
||||
* Presence of file Uris decides whether the device with the activity open is a sender or receiver:
|
||||
* - On the sender device, this activity is started from the app chooser post selection
|
||||
* of files to share in the Library
|
||||
* - On the receiver device, the activity is started directly from within the 'Get Content'
|
||||
* activity, without any file Uris
|
||||
* */
|
||||
Intent filesIntent = getIntent();
|
||||
ArrayList<Uri> fileUriArrayList;
|
||||
fileUriArrayList = filesIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
|
||||
isFileSender = (fileUriArrayList != null && fileUriArrayList.size() > 0);
|
||||
|
||||
setSupportActionBar(actionBar);
|
||||
actionBar.setNavigationIcon(R.drawable.ic_close_white_24dp);
|
||||
actionBar.setNavigationOnClickListener(v -> finish());
|
||||
|
||||
wifiPeerListAdapter = new WifiPeerListAdapter(
|
||||
new WifiP2pDelegate(wifiP2pDevice -> {
|
||||
wifiDirectManager.sendToDevice(wifiP2pDevice);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
)
|
||||
);
|
||||
peerDeviceList.setAdapter(wifiPeerListAdapter);
|
||||
peerDeviceList.setLayoutManager(new LinearLayoutManager(this));
|
||||
peerDeviceList.setHasFixedSize(true);
|
||||
|
||||
if (isFileSender) {
|
||||
for (int i = 0; i < fileUriArrayList.size(); i++) {
|
||||
filesForTransfer.add(new FileItem(fileUriArrayList.get(i)));
|
||||
}
|
||||
|
||||
displayFileTransferProgress(filesForTransfer);
|
||||
}
|
||||
|
||||
wifiDirectManager.startWifiDirectManager(filesForTransfer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.wifi_file_share_items, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
if (item.getItemId() == R.id.menu_item_search_devices) {
|
||||
|
||||
/* Permissions essential for this module */
|
||||
if (!checkCoarseLocationAccessPermission()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!checkExternalStorageWritePermission()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Initiate discovery */
|
||||
if (!wifiDirectManager.isWifiP2pEnabled()) {
|
||||
requestEnableWifiP2pServices();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isLocationServiceEnabled()) {
|
||||
requestEnableLocationServices();
|
||||
return true;
|
||||
}
|
||||
|
||||
showPeerDiscoveryProgressBar();
|
||||
wifiDirectManager.discoverPeerDevices();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void showPeerDiscoveryProgressBar() { // Setup UI for searching peers
|
||||
searchingPeersProgressBar.setVisibility(View.VISIBLE);
|
||||
peerDeviceList.setVisibility(View.INVISIBLE);
|
||||
textViewPeerDevices.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
/* From WifiDirectManager.Callbacks interface */
|
||||
@Override
|
||||
public void onUserDeviceDetailsAvailable(@Nullable WifiP2pDevice userDevice) {
|
||||
// Update UI with user device's details
|
||||
if (userDevice != null) {
|
||||
deviceName.setText(userDevice.deviceName);
|
||||
Log.d(TAG, WifiDirectManager.getDeviceStatus(userDevice.status));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionToPeersLost() {
|
||||
wifiPeerListAdapter.setItems(Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFilesForTransferAvailable(@NonNull ArrayList<FileItem> filesForTransfer) {
|
||||
this.filesForTransfer = filesForTransfer;
|
||||
displayFileTransferProgress(filesForTransfer);
|
||||
}
|
||||
|
||||
private void displayFileTransferProgress(@NonNull ArrayList<FileItem> filesToSend) {
|
||||
fileListAdapter = new FileListAdapter(filesToSend);
|
||||
filesRecyclerView.setAdapter(fileListAdapter);
|
||||
filesRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileStatusChanged(int itemIndex) {
|
||||
fileListAdapter.notifyItemChanged(itemIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOfAvailablePeers(@NonNull WifiP2pDeviceList peers) {
|
||||
final List<WifiP2pDevice> deviceList = new ArrayList(peers.getDeviceList());
|
||||
|
||||
searchingPeersProgressBar.setVisibility(View.GONE);
|
||||
peerDeviceList.setVisibility(View.VISIBLE);
|
||||
wifiPeerListAdapter.setItems(deviceList);
|
||||
|
||||
if (deviceList.size() == 0) {
|
||||
Log.d(LocalFileTransferActivity.TAG, "No devices found");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileTransferComplete() {
|
||||
finish();
|
||||
}
|
||||
|
||||
/* Helper methods used for checking permissions and states of services */
|
||||
private boolean checkCoarseLocationAccessPermission() { // Required by Android to detect wifi-p2p peers
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||
== PackageManager.PERMISSION_DENIED) {
|
||||
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION)) {
|
||||
alertDialogShower.show(KiwixDialog.LocationPermissionRationale.INSTANCE,
|
||||
(Function0<Unit>) () -> {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[] { Manifest.permission.ACCESS_COARSE_LOCATION },
|
||||
PERMISSION_REQUEST_CODE_COARSE_LOCATION);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[] { Manifest.permission.ACCESS_COARSE_LOCATION },
|
||||
PERMISSION_REQUEST_CODE_COARSE_LOCATION);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true; // Control reaches here: Either permission granted at install time, or at the time of request
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkExternalStorageWritePermission() { // To access and store the zims
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
== PackageManager.PERMISSION_DENIED) {
|
||||
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
alertDialogShower.show(KiwixDialog.StoragePermissionRationale.INSTANCE,
|
||||
new Function0<Unit>() {
|
||||
@Override public Unit invoke() {
|
||||
ActivityCompat.requestPermissions(LocalFileTransferActivity.this,
|
||||
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
|
||||
PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
|
||||
PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true; // Control reaches here: Either permission granted at install time, or at the time of request
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
|
||||
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
|
||||
switch (requestCode) {
|
||||
|
||||
case PERMISSION_REQUEST_CODE_COARSE_LOCATION: {
|
||||
Log.e(TAG, "Location permission not granted");
|
||||
|
||||
showToast(this, R.string.permission_refused_location, Toast.LENGTH_LONG);
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
|
||||
case PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS: {
|
||||
Log.e(TAG, "Storage write permission not granted");
|
||||
|
||||
showToast(this, R.string.permission_refused_storage, Toast.LENGTH_LONG);
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLocationServiceEnabled() {
|
||||
return isProviderEnabled(LocationManager.GPS_PROVIDER)
|
||||
|| isProviderEnabled(LocationManager.NETWORK_PROVIDER);
|
||||
}
|
||||
|
||||
private boolean isProviderEnabled(String locationProvider) {
|
||||
try {
|
||||
return locationManager.isProviderEnabled(locationProvider);
|
||||
} catch (SecurityException | IllegalArgumentException ex) {
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void requestEnableLocationServices() {
|
||||
alertDialogShower.show(KiwixDialog.EnableLocationServices.INSTANCE,
|
||||
new Function0<Unit>() {
|
||||
@Override public Unit invoke() {
|
||||
startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS),
|
||||
REQUEST_ENABLE_LOCATION_SERVICES);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
},
|
||||
new Function0<Unit>() {
|
||||
@Override public Unit invoke() {
|
||||
showToast(LocalFileTransferActivity.this, R.string.discovery_needs_location,
|
||||
Toast.LENGTH_SHORT);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void requestEnableWifiP2pServices() {
|
||||
alertDialogShower.show(KiwixDialog.EnableWifiP2pServices.INSTANCE,
|
||||
new Function0<Unit>() {
|
||||
@Override public Unit invoke() {
|
||||
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
},
|
||||
new Function0<Unit>() {
|
||||
@Override public Unit invoke() {
|
||||
showToast(LocalFileTransferActivity.this, R.string.discovery_needs_wifi,
|
||||
Toast.LENGTH_SHORT);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_ENABLE_LOCATION_SERVICES: {
|
||||
if (!isLocationServiceEnabled()) {
|
||||
showToast(this, R.string.permission_refused_location, Toast.LENGTH_LONG);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Miscellaneous helper methods */
|
||||
static void showToast(Context context, int stringResource, int duration) {
|
||||
showToast(context, context.getString(stringResource), duration);
|
||||
}
|
||||
|
||||
static void showToast(Context context, String text, int duration) {
|
||||
Toast.makeText(context, text, duration).show();
|
||||
}
|
||||
|
||||
@Override protected void onDestroy() {
|
||||
wifiDirectManager.stopWifiDirectManager();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override protected void injection(CoreComponent coreComponent) {
|
||||
ActivityExtensionsKt.getKiwixActivityComponent(this).inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.local_file_transfer
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.location.LocationManager
|
||||
import android.net.Uri
|
||||
import android.net.wifi.p2p.WifiP2pDevice
|
||||
import android.net.wifi.p2p.WifiP2pDeviceList
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import butterknife.BindView
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||
import org.kiwix.kiwixmobile.core.di.components.CoreComponent
|
||||
import org.kiwix.kiwixmobile.core.utils.AlertDialogShower
|
||||
import org.kiwix.kiwixmobile.core.utils.KiwixDialog
|
||||
import org.kiwix.kiwixmobile.kiwixActivityComponent
|
||||
import org.kiwix.kiwixmobile.local_file_transfer.WifiDirectManager.Companion.getDeviceStatus
|
||||
import org.kiwix.kiwixmobile.local_file_transfer.adapter.WifiP2pDelegate
|
||||
import org.kiwix.kiwixmobile.local_file_transfer.adapter.WifiPeerListAdapter
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Created by @Aditya-Sood as a part of GSoC 2019.
|
||||
*
|
||||
* This activity is the starting point for the module used for sharing zims between devices.
|
||||
*
|
||||
* The module is used for transferring ZIM files from one device to another, from within the
|
||||
* app. Two devices are connected to each other using WiFi Direct, followed by file transfer.
|
||||
*
|
||||
* File transfer involves two phases:
|
||||
* 1) Handshake with the selected peer device, using [PeerGroupHandshakeAsyncTask]
|
||||
* 2) After handshake, starting the files transfer using [SenderDeviceAsyncTask] on the sender
|
||||
* device and [ReceiverDeviceAsyncTask] files receiving device
|
||||
*/
|
||||
@SuppressLint("GoogleAppIndexingApiWarning")
|
||||
class LocalFileTransferActivity : BaseActivity(),
|
||||
WifiDirectManager.Callbacks {
|
||||
@Inject
|
||||
var alertDialogShower: AlertDialogShower? = null
|
||||
|
||||
@Inject
|
||||
var wifiDirectManager: WifiDirectManager? = null
|
||||
|
||||
@Inject
|
||||
var locationManager: LocationManager? = null
|
||||
|
||||
@BindView(R.id.toolbar)
|
||||
var actionBar: Toolbar? = null
|
||||
|
||||
@BindView(R.id.text_view_device_name)
|
||||
var deviceName: TextView? = null
|
||||
|
||||
@BindView(R.id.progress_bar_searching_peers)
|
||||
var searchingPeersProgressBar: ProgressBar? = null
|
||||
|
||||
@BindView(R.id.list_peer_devices)
|
||||
var peerDeviceList: RecyclerView? = null
|
||||
|
||||
@BindView(R.id.text_view_empty_peer_list)
|
||||
var textViewPeerDevices: TextView? = null
|
||||
|
||||
@BindView(R.id.recycler_view_transfer_files)
|
||||
var filesRecyclerView: RecyclerView? = null
|
||||
private var isFileSender = false // Whether the device is the file sender or not
|
||||
private var filesForTransfer = ArrayList<FileItem>()
|
||||
private var fileListAdapter: FileListAdapter? = null
|
||||
private var wifiPeerListAdapter: WifiPeerListAdapter? = null
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_local_file_transfer)
|
||||
/*
|
||||
* Presence of file Uris decides whether the device with the activity open is a sender or receiver:
|
||||
* - On the sender device, this activity is started from the app chooser post selection
|
||||
* of files to share in the Library
|
||||
* - On the receiver device, the activity is started directly from within the 'Get Content'
|
||||
* activity, without any file Uris
|
||||
* */
|
||||
val filesIntent = intent
|
||||
val fileUriArrayList: ArrayList<Uri>?
|
||||
fileUriArrayList = filesIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)
|
||||
isFileSender = fileUriArrayList != null && fileUriArrayList.size > 0
|
||||
setSupportActionBar(actionBar)
|
||||
actionBar!!.setNavigationIcon(R.drawable.ic_close_white_24dp)
|
||||
actionBar!!.setNavigationOnClickListener { finish() }
|
||||
wifiPeerListAdapter = WifiPeerListAdapter(
|
||||
WifiP2pDelegate { wifiP2pDevice: WifiP2pDevice? ->
|
||||
wifiDirectManager!!.sendToDevice(wifiP2pDevice!!)
|
||||
}
|
||||
)
|
||||
peerDeviceList!!.adapter = wifiPeerListAdapter
|
||||
peerDeviceList!!.layoutManager = LinearLayoutManager(this)
|
||||
peerDeviceList!!.setHasFixedSize(true)
|
||||
if (isFileSender) {
|
||||
for (i in fileUriArrayList.indices) {
|
||||
filesForTransfer.add(FileItem(fileUriArrayList[i]))
|
||||
}
|
||||
displayFileTransferProgress(filesForTransfer)
|
||||
}
|
||||
wifiDirectManager!!.startWifiDirectManager(filesForTransfer)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.wifi_file_share_items, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return if (item.itemId == R.id.menu_item_search_devices) {
|
||||
|
||||
/* Permissions essential for this module */
|
||||
if (!checkCoarseLocationAccessPermission()) {
|
||||
return true
|
||||
}
|
||||
if (!checkExternalStorageWritePermission()) {
|
||||
return true
|
||||
}
|
||||
|
||||
/* Initiate discovery */if (!wifiDirectManager!!.isWifiP2pEnabled) {
|
||||
requestEnableWifiP2pServices()
|
||||
return true
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isLocationServiceEnabled) {
|
||||
requestEnableLocationServices()
|
||||
return true
|
||||
}
|
||||
showPeerDiscoveryProgressBar()
|
||||
wifiDirectManager!!.discoverPeerDevices()
|
||||
true
|
||||
} else {
|
||||
super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPeerDiscoveryProgressBar() { // Setup UI for searching peers
|
||||
searchingPeersProgressBar!!.visibility = View.VISIBLE
|
||||
peerDeviceList!!.visibility = View.INVISIBLE
|
||||
textViewPeerDevices!!.visibility = View.INVISIBLE
|
||||
}
|
||||
|
||||
/* From WifiDirectManager.Callbacks interface */
|
||||
override fun onUserDeviceDetailsAvailable(userDevice: WifiP2pDevice?) {
|
||||
// Update UI with user device's details
|
||||
if (userDevice != null) {
|
||||
deviceName!!.text = userDevice.deviceName
|
||||
Log.d(
|
||||
TAG,
|
||||
getDeviceStatus(userDevice.status)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConnectionToPeersLost() {
|
||||
wifiPeerListAdapter!!.items = Collections.EMPTY_LIST as List<WifiP2pDevice>
|
||||
}
|
||||
|
||||
override fun onFilesForTransferAvailable(filesForTransfer: ArrayList<FileItem>) {
|
||||
this.filesForTransfer = filesForTransfer
|
||||
displayFileTransferProgress(filesForTransfer)
|
||||
}
|
||||
|
||||
private fun displayFileTransferProgress(filesToSend: ArrayList<FileItem>) {
|
||||
fileListAdapter = FileListAdapter(filesToSend)
|
||||
filesRecyclerView!!.adapter = fileListAdapter
|
||||
filesRecyclerView!!.layoutManager = LinearLayoutManager(this)
|
||||
}
|
||||
|
||||
override fun onFileStatusChanged(itemIndex: Int) {
|
||||
fileListAdapter!!.notifyItemChanged(itemIndex)
|
||||
}
|
||||
|
||||
override fun updateListOfAvailablePeers(peers: WifiP2pDeviceList) {
|
||||
val deviceList: List<WifiP2pDevice> = ArrayList<WifiP2pDevice>(peers.deviceList)
|
||||
searchingPeersProgressBar!!.visibility = View.GONE
|
||||
peerDeviceList!!.visibility = View.VISIBLE
|
||||
wifiPeerListAdapter!!.items = deviceList
|
||||
if (deviceList.isEmpty()) {
|
||||
Log.d(TAG, "No devices found")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFileTransferComplete() {
|
||||
finish()
|
||||
}
|
||||
|
||||
/* Helper methods used for checking permissions and states of services */
|
||||
private fun checkCoarseLocationAccessPermission(): Boolean { // Required by Android to detect wifi-p2p peers
|
||||
return if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||
== PackageManager.PERMISSION_DENIED
|
||||
) {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(
|
||||
this,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
)
|
||||
) {
|
||||
alertDialogShower!!.show(KiwixDialog.LocationPermissionRationale,
|
||||
{
|
||||
ActivityCompat.requestPermissions(
|
||||
this, arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
|
||||
PERMISSION_REQUEST_CODE_COARSE_LOCATION
|
||||
)
|
||||
})
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(
|
||||
this, arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
|
||||
PERMISSION_REQUEST_CODE_COARSE_LOCATION
|
||||
)
|
||||
}
|
||||
false
|
||||
} else {
|
||||
true // Control reaches here: Either permission granted at install time, or at the time of request
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkExternalStorageWritePermission(): Boolean { // To access and store the zims
|
||||
return if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
== PackageManager.PERMISSION_DENIED
|
||||
) {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(
|
||||
this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
)
|
||||
) {
|
||||
alertDialogShower!!.show(KiwixDialog.StoragePermissionRationale, {
|
||||
ActivityCompat.requestPermissions(
|
||||
this@LocalFileTransferActivity,
|
||||
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
|
||||
PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS
|
||||
)
|
||||
})
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(
|
||||
this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
|
||||
PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS
|
||||
)
|
||||
}
|
||||
false
|
||||
} else {
|
||||
true // Control reaches here: Either permission granted at install time, or at the time of request
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int, permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
|
||||
when (requestCode) {
|
||||
PERMISSION_REQUEST_CODE_COARSE_LOCATION -> {
|
||||
Log.e(
|
||||
TAG,
|
||||
"Location permission not granted"
|
||||
)
|
||||
showToast(
|
||||
this,
|
||||
R.string.permission_refused_location,
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
finish()
|
||||
}
|
||||
PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS -> {
|
||||
Log.e(
|
||||
TAG,
|
||||
"Storage write permission not granted"
|
||||
)
|
||||
showToast(
|
||||
this,
|
||||
R.string.permission_refused_storage,
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
finish()
|
||||
}
|
||||
else -> {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val isLocationServiceEnabled: Boolean
|
||||
get() = (isProviderEnabled(LocationManager.GPS_PROVIDER)
|
||||
|| isProviderEnabled(LocationManager.NETWORK_PROVIDER))
|
||||
|
||||
private fun isProviderEnabled(locationProvider: String): Boolean {
|
||||
return try {
|
||||
locationManager!!.isProviderEnabled(locationProvider)
|
||||
} catch (ex: SecurityException) {
|
||||
ex.printStackTrace()
|
||||
false
|
||||
} catch (ex: IllegalArgumentException) {
|
||||
ex.printStackTrace()
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestEnableLocationServices() {
|
||||
alertDialogShower!!.show(KiwixDialog.EnableLocationServices, {
|
||||
startActivityForResult(
|
||||
Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS),
|
||||
REQUEST_ENABLE_LOCATION_SERVICES
|
||||
)
|
||||
}, {
|
||||
showToast(
|
||||
this@LocalFileTransferActivity, R.string.discovery_needs_location,
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
private fun requestEnableWifiP2pServices() {
|
||||
alertDialogShower!!.show(KiwixDialog.EnableWifiP2pServices, {
|
||||
startActivity(Intent(Settings.ACTION_WIFI_SETTINGS))
|
||||
}, {
|
||||
showToast(
|
||||
this@LocalFileTransferActivity, R.string.discovery_needs_wifi,
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
override fun onActivityResult(
|
||||
requestCode: Int,
|
||||
resultCode: Int,
|
||||
data: Intent?
|
||||
) {
|
||||
when (requestCode) {
|
||||
REQUEST_ENABLE_LOCATION_SERVICES -> {
|
||||
if (!isLocationServiceEnabled) {
|
||||
showToast(
|
||||
this,
|
||||
R.string.permission_refused_location,
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
wifiDirectManager!!.stopWifiDirectManager()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun injection(coreComponent: CoreComponent) {
|
||||
this.kiwixActivityComponent.inject(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Not a typo, 'Log' tags have a length upper limit of 25 characters
|
||||
const val TAG = "LocalFileTransferActvty"
|
||||
const val REQUEST_ENABLE_LOCATION_SERVICES = 1
|
||||
private const val PERMISSION_REQUEST_CODE_COARSE_LOCATION = 1
|
||||
private const val PERMISSION_REQUEST_CODE_STORAGE_WRITE_ACCESS = 2
|
||||
|
||||
/* Miscellaneous helper methods */
|
||||
fun showToast(
|
||||
context: Context,
|
||||
stringResource: Int,
|
||||
duration: Int
|
||||
) {
|
||||
showToast(
|
||||
context,
|
||||
context.getString(stringResource),
|
||||
duration
|
||||
)
|
||||
}
|
||||
|
||||
private fun showToast(
|
||||
context: Context?,
|
||||
text: String?,
|
||||
duration: Int
|
||||
) {
|
||||
Toast.makeText(context, text, duration).show()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user