Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
savoirfairelinux
jami-client-android
Commits
79b6d163
Commit
79b6d163
authored
Jun 08, 2021
by
Adrien Béraud
Browse files
file transfer: update for new API
Change-Id: I24add1f0bcdb5847245dc66f84585bd65d6e7042
parent
b7f1f383
Changes
24
Hide whitespace changes
Inline
Side-by-side
build-daemon.sh
View file @
79b6d163
...
...
@@ -181,8 +181,8 @@ STATIC_LIBS_ALL="-llog -lOpenSLES -landroid \
-lyaml-cpp -ljsoncpp -lhttp_parser -lfmt
\
-luuid -lz -ldl
\
-lvpx -lopus -lspeex -lspeexdsp -lx264
\
-largon2
\
-lgit2
\
-largon2
\
-liconv"
LIBRING_JNI_DIR
=
${
ANDROID_APP_DIR
}
/app/src/main/libs/
${
ANDROID_ABI
}
...
...
ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.java
View file @
79b6d163
...
...
@@ -442,31 +442,19 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo
if
(
interaction
.
getType
()
==
(
InteractionType
.
CONTACT
))
return
false
;
switch
(
item
.
getItemId
())
{
case
R
.
id
.
conv_action_download
:
{
presenter
.
saveFile
(
interaction
);
break
;
}
case
R
.
id
.
conv_action_share
:
{
presenter
.
shareFile
(
interaction
);
break
;
}
case
R
.
id
.
conv_action_open
:
{
presenter
.
openFile
(
interaction
);
break
;
}
case
R
.
id
.
conv_action_delete
:
{
presenter
.
deleteConversationItem
(
interaction
);
break
;
}
case
R
.
id
.
conv_action_cancel_message
:
{
presenter
.
cancelMessage
(
interaction
);
break
;
}
case
R
.
id
.
conv_action_copy_text
:
{
addToClipboard
((
interaction
).
getBody
());
break
;
}
int
itemId
=
item
.
getItemId
();
if
(
itemId
==
R
.
id
.
conv_action_download
)
{
presenter
.
saveFile
(
interaction
);
}
else
if
(
itemId
==
R
.
id
.
conv_action_share
)
{
presenter
.
shareFile
(
interaction
);
}
else
if
(
itemId
==
R
.
id
.
conv_action_open
)
{
presenter
.
openFile
(
interaction
);
}
else
if
(
itemId
==
R
.
id
.
conv_action_delete
)
{
presenter
.
deleteConversationItem
(
interaction
);
}
else
if
(
itemId
==
R
.
id
.
conv_action_cancel_message
)
{
presenter
.
cancelMessage
(
interaction
);
}
else
if
(
itemId
==
R
.
id
.
conv_action_copy_text
)
{
addToClipboard
((
interaction
).
getBody
());
}
return
true
;
}
...
...
@@ -487,8 +475,10 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo
viewHolder
.
mImage
.
setOnClickListener
(
v
->
{
Uri
contentUri
=
ContentUriHandler
.
getUriForFile
(
v
.
getContext
(),
ContentUriHandler
.
AUTHORITY_FILES
,
path
);
Intent
i
=
new
Intent
(
context
,
MediaViewerActivity
.
class
);
i
.
setAction
(
Intent
.
ACTION_VIEW
).
setDataAndType
(
contentUri
,
"image/*"
).
setFlags
(
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
);
Intent
i
=
new
Intent
(
context
,
MediaViewerActivity
.
class
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
setDataAndType
(
contentUri
,
"image/*"
)
.
setFlags
(
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
);
ActivityOptionsCompat
options
=
ActivityOptionsCompat
.
makeSceneTransitionAnimation
(
conversationFragment
.
getActivity
(),
viewHolder
.
mImage
,
"picture"
);
conversationFragment
.
startActivityForResult
(
i
,
3006
,
options
.
toBundle
());
...
...
@@ -628,23 +618,24 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo
private
void
configureForFileInfo
(
@NonNull
final
ConversationViewHolder
viewHolder
,
@NonNull
final
Interaction
interaction
,
int
position
)
{
DataTransfer
file
=
(
DataTransfer
)
interaction
;
File
path
=
presenter
.
getDeviceRuntimeService
().
getConversationPath
(
interaction
.
getConversationId
()
==
null
?
interaction
.
getConversation
().
getParticipant
()
:
interaction
.
getConversationId
(),
file
.
getStoragePath
());
File
path
=
presenter
.
getDeviceRuntimeService
().
getConversationPath
(
file
);
if
(
file
.
isComplete
())
file
.
setSize
(
path
.
length
());
String
timeString
=
timestampToDetailString
(
viewHolder
.
itemView
.
getContext
(),
file
.
getTimestamp
());
viewHolder
.
compositeDisposable
.
add
(
timestampUpdateTimer
.
subscribe
(
t
->
{
if
(
file
.
getStatus
()
==
InteractionStatus
.
TRANSFER_FINISHED
)
{
viewHolder
.
compositeDisposable
.
add
(
timestampUpdateTimer
.
subscribe
(
time
->
{
InteractionStatus
status
=
file
.
getStatus
();
if
(
status
==
InteractionStatus
.
TRANSFER_FINISHED
)
{
viewHolder
.
mMsgDetailTxt
.
setText
(
String
.
format
(
"%s - %s"
,
timeString
,
Formatter
.
formatFileSize
(
viewHolder
.
itemView
.
getContext
(),
file
.
getTotalSize
())));
}
else
if
(
file
.
getS
tatus
()
==
InteractionStatus
.
TRANSFER_ONGOING
)
{
}
else
if
(
s
tatus
==
InteractionStatus
.
TRANSFER_ONGOING
)
{
viewHolder
.
mMsgDetailTxt
.
setText
(
String
.
format
(
"%s / %s - %s"
,
Formatter
.
formatFileSize
(
viewHolder
.
itemView
.
getContext
(),
file
.
getBytesProgress
()),
Formatter
.
formatFileSize
(
viewHolder
.
itemView
.
getContext
(),
file
.
getTotalSize
()),
ResourceMapper
.
getReadableFileTransferStatus
(
conversationFragment
.
getActivity
(),
file
.
getS
tatus
()
)));
ResourceMapper
.
getReadableFileTransferStatus
(
viewHolder
.
itemView
.
getContext
(),
s
tatus
)));
}
else
{
viewHolder
.
mMsgDetailTxt
.
setText
(
String
.
format
(
"%s - %s - %s"
,
timeString
,
Formatter
.
formatFileSize
(
viewHolder
.
itemView
.
getContext
(),
file
.
getTotalSize
()),
ResourceMapper
.
getReadableFileTransferStatus
(
conversationFragment
.
getActivity
(),
file
.
getS
tatus
()
)));
ResourceMapper
.
getReadableFileTransferStatus
(
viewHolder
.
itemView
.
getContext
(),
s
tatus
)));
}
}));
...
...
@@ -731,7 +722,8 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo
}
else
if
(
type
==
TransferMsgType
.
AUDIO
)
{
configureAudio
(
viewHolder
,
path
);
}
else
{
if
(
file
.
getStatus
().
isError
())
{
InteractionStatus
status
=
file
.
getStatus
();
if
(
status
.
isError
())
{
viewHolder
.
mIcon
.
setImageResource
(
R
.
drawable
.
baseline_warning_24
);
}
else
{
viewHolder
.
mIcon
.
setImageResource
(
R
.
drawable
.
baseline_attach_file_24
);
...
...
@@ -739,13 +731,18 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo
viewHolder
.
mMsgTxt
.
setText
(
file
.
getDisplayName
());
if
(
file
.
getStatus
()
==
InteractionStatus
.
TRANSFER_AWAITING_HOST
)
{
if
(
status
==
InteractionStatus
.
TRANSFER_AWAITING_HOST
)
{
viewHolder
.
btnRefuse
.
setVisibility
(
View
.
VISIBLE
);
viewHolder
.
mAnswerLayout
.
setVisibility
(
View
.
VISIBLE
);
viewHolder
.
btnAccept
.
setOnClickListener
(
v
->
presenter
.
acceptFile
(
file
));
viewHolder
.
btnRefuse
.
setOnClickListener
(
v
->
presenter
.
refuseFile
(
file
));
}
else
if
(
status
==
InteractionStatus
.
FILE_AVAILABLE
)
{
viewHolder
.
btnRefuse
.
setVisibility
(
View
.
GONE
);
viewHolder
.
mAnswerLayout
.
setVisibility
(
View
.
VISIBLE
);
viewHolder
.
btnAccept
.
setOnClickListener
(
v
->
presenter
.
acceptFile
(
file
));
}
else
{
viewHolder
.
mAnswerLayout
.
setVisibility
(
View
.
GONE
);
if
(
file
.
getS
tatus
()
==
InteractionStatus
.
TRANSFER_ONGOING
)
{
if
(
s
tatus
==
InteractionStatus
.
TRANSFER_ONGOING
)
{
viewHolder
.
progress
.
setMax
((
int
)
(
file
.
getTotalSize
()
/
1024
));
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N
)
{
viewHolder
.
progress
.
setProgress
((
int
)
(
file
.
getBytesProgress
()
/
1024
),
true
);
...
...
@@ -1194,14 +1191,14 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo
FIRST
,
MIDDLE
,
LAST
,
SINGLE
;
SINGLE
}
private
enum
TransferMsgType
{
FILE
,
IMAGE
,
AUDIO
,
VIDEO
;
VIDEO
}
public
enum
MessageType
{
INCOMING_FILE
(
R
.
layout
.
item_conv_file_peer
),
...
...
ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.java
View file @
79b6d163
...
...
@@ -759,23 +759,25 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
return
;
}
requireActivity
().
startService
(
new
Intent
(
DRingService
.
ACTION_FILE_ACCEPT
,
ConversationPath
.
toUri
(
accountId
,
conversationUri
),
requireContext
(),
DRingService
.
class
)
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
transfer
.
getDaemonId
()));
.
putExtra
(
DRingService
.
KEY_MESSAGE_ID
,
transfer
.
getMessageId
())
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
transfer
.
getFileId
()));
}
@Override
public
void
refuseFile
(
String
accountId
,
Uri
conversationUri
,
DataTransfer
transfer
)
{
requireActivity
().
startService
(
new
Intent
(
DRingService
.
ACTION_FILE_CANCEL
,
ConversationPath
.
toUri
(
accountId
,
conversationUri
),
requireContext
(),
DRingService
.
class
)
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
transfer
.
getDaemonId
()));
.
putExtra
(
DRingService
.
KEY_MESSAGE_ID
,
transfer
.
getMessageId
())
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
transfer
.
getFileId
()));
}
@Override
public
void
shareFile
(
File
path
)
{
public
void
shareFile
(
File
path
,
String
displayName
)
{
Context
c
=
getContext
();
if
(
c
==
null
)
return
;
android
.
net
.
Uri
fileUri
=
null
;
try
{
fileUri
=
ContentUriHandler
.
getUriForFile
(
c
,
ContentUriHandler
.
AUTHORITY_FILES
,
path
);
fileUri
=
ContentUriHandler
.
getUriForFile
(
c
,
ContentUriHandler
.
AUTHORITY_FILES
,
path
,
displayName
);
}
catch
(
IllegalArgumentException
e
)
{
Log
.
e
(
"File Selector"
,
"The selected file can't be shared: "
+
path
.
getName
());
}
...
...
@@ -783,7 +785,7 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
Intent
sendIntent
=
new
Intent
();
sendIntent
.
setAction
(
Intent
.
ACTION_SEND
);
sendIntent
.
addFlags
(
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
);
String
type
=
c
.
getContentResolver
().
getType
(
fileUri
);
String
type
=
c
.
getContentResolver
().
getType
(
fileUri
.
buildUpon
().
appendPath
(
displayName
).
build
()
);
sendIntent
.
setDataAndType
(
fileUri
,
type
);
sendIntent
.
putExtra
(
Intent
.
EXTRA_STREAM
,
fileUri
);
startActivity
(
Intent
.
createChooser
(
sendIntent
,
null
));
...
...
@@ -791,13 +793,13 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
}
@Override
public
void
openFile
(
File
path
)
{
public
void
openFile
(
File
path
,
String
displayName
)
{
Context
c
=
getContext
();
if
(
c
==
null
)
return
;
android
.
net
.
Uri
fileUri
=
null
;
try
{
fileUri
=
ContentUriHandler
.
getUriForFile
(
c
,
ContentUriHandler
.
AUTHORITY_FILES
,
path
);
fileUri
=
ContentUriHandler
.
getUriForFile
(
c
,
ContentUriHandler
.
AUTHORITY_FILES
,
path
,
displayName
);
}
catch
(
IllegalArgumentException
e
)
{
Log
.
e
(
TAG
,
"The selected file can't be shared: "
+
path
.
getName
());
}
...
...
@@ -805,7 +807,7 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
Intent
sendIntent
=
new
Intent
();
sendIntent
.
setAction
(
Intent
.
ACTION_VIEW
);
sendIntent
.
addFlags
(
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
);
String
type
=
c
.
getContentResolver
().
getType
(
fileUri
);
String
type
=
c
.
getContentResolver
().
getType
(
fileUri
.
buildUpon
().
appendPath
(
displayName
).
build
()
);
sendIntent
.
setDataAndType
(
fileUri
,
type
);
sendIntent
.
putExtra
(
Intent
.
EXTRA_STREAM
,
fileUri
);
//startActivity(Intent.createChooser(sendIntent, null));
...
...
ring-android/app/src/main/java/cx/ring/service/DRingService.java
View file @
79b6d163
...
...
@@ -97,6 +97,7 @@ public class DRingService extends Service {
static
public
final
String
ACTION_FILE_ACCEPT
=
BuildConfig
.
APPLICATION_ID
+
".action.FILE_ACCEPT"
;
static
public
final
String
ACTION_FILE_CANCEL
=
BuildConfig
.
APPLICATION_ID
+
".action.FILE_CANCEL"
;
static
public
final
String
KEY_MESSAGE_ID
=
"messageId"
;
static
public
final
String
KEY_TRANSFER_ID
=
"transferId"
;
static
public
final
String
KEY_TEXT_REPLY
=
"textReply"
;
...
...
@@ -651,13 +652,14 @@ public class DRingService extends Service {
}
private
void
handleFileAction
(
android
.
net
.
Uri
uri
,
String
action
,
Bundle
extras
)
{
long
id
=
extras
.
getLong
(
KEY_TRANSFER_ID
);
String
messageId
=
extras
.
getString
(
KEY_MESSAGE_ID
);
String
id
=
extras
.
getString
(
KEY_TRANSFER_ID
);
ConversationPath
path
=
ConversationPath
.
fromUri
(
uri
);
if
(
action
.
equals
(
ACTION_FILE_ACCEPT
))
{
mNotificationService
.
removeTransferNotification
(
path
.
getAccountId
(),
path
.
getConversationUri
(),
id
);
mAccountService
.
acceptFileTransfer
(
path
.
getAccountId
(),
path
.
getConversationUri
(),
id
);
mAccountService
.
acceptFileTransfer
(
path
.
getAccountId
(),
path
.
getConversationUri
(),
messageId
,
id
);
}
else
if
(
action
.
equals
(
ACTION_FILE_CANCEL
))
{
mConversationFacade
.
cancelFileTransfer
(
path
.
getAccountId
(),
path
.
getConversationUri
(),
id
);
mConversationFacade
.
cancelFileTransfer
(
path
.
getAccountId
(),
path
.
getConversationUri
(),
messageId
,
id
);
}
}
...
...
ring-android/app/src/main/java/cx/ring/services/DeviceRuntimeServiceImpl.java
View file @
79b6d163
...
...
@@ -97,6 +97,11 @@ public class DeviceRuntimeServiceImpl extends DeviceRuntimeService {
return
AndroidFileUtils
.
getConversationPath
(
mContext
,
conversationId
,
name
);
}
@Override
public
File
getConversationPath
(
String
accountId
,
String
conversationId
,
String
name
)
{
return
AndroidFileUtils
.
getConversationPath
(
mContext
,
accountId
,
conversationId
,
name
);
}
@Override
public
File
getTemporaryPath
(
String
conversationId
,
String
name
)
{
return
AndroidFileUtils
.
getTempPath
(
mContext
,
conversationId
,
name
);
...
...
ring-android/app/src/main/java/cx/ring/services/NotificationServiceImpl.java
View file @
79b6d163
...
...
@@ -471,12 +471,12 @@ public class NotificationServiceImpl implements NotificationService {
if
(!
remove
)
{
showFileTransferNotification
(
conversation
,
transfer
);
}
else
{
removeTransferNotification
(
ConversationPath
.
toUri
(
conversation
),
transfer
.
get
Daemon
Id
());
removeTransferNotification
(
ConversationPath
.
toUri
(
conversation
),
transfer
.
get
File
Id
());
}
}
@Override
public
void
removeTransferNotification
(
String
accountId
,
Uri
conversationUri
,
lo
ng
transferId
)
{
public
void
removeTransferNotification
(
String
accountId
,
Uri
conversationUri
,
Stri
ng
transferId
)
{
removeTransferNotification
(
ConversationPath
.
toUri
(
accountId
,
conversationUri
),
transferId
);
}
...
...
@@ -485,7 +485,7 @@ public class NotificationServiceImpl implements NotificationService {
*
* @param transferId the transfer id which is required to generate the notification id
*/
public
void
removeTransferNotification
(
android
.
net
.
Uri
path
,
lo
ng
transferId
)
{
public
void
removeTransferNotification
(
android
.
net
.
Uri
path
,
Stri
ng
transferId
)
{
int
id
=
getFileTransferNotificationId
(
path
,
transferId
);
dataTransferNotifications
.
remove
(
id
);
cancelFileNotification
(
id
,
false
);
...
...
@@ -749,7 +749,7 @@ public class NotificationServiceImpl implements NotificationService {
}
android
.
net
.
Uri
path
=
ConversationPath
.
toUri
(
conversation
);
Log
.
d
(
TAG
,
"showFileTransferNotification "
+
path
);
lo
ng
dataTransferId
=
info
.
get
Daemon
Id
();
Stri
ng
dataTransferId
=
info
.
get
File
Id
();
int
notificationId
=
getFileTransferNotificationId
(
path
,
dataTransferId
);
Intent
intentConversation
=
new
Intent
(
DRingService
.
ACTION_CONV_ACCEPT
,
path
,
mContext
,
DRingService
.
class
);
...
...
@@ -955,7 +955,7 @@ public class NotificationServiceImpl implements NotificationService {
return
(
NOTIF_MSG
+
accountId
+
contact
.
toString
()).
hashCode
();
}
private
int
getFileTransferNotificationId
(
android
.
net
.
Uri
path
,
lo
ng
dataTransferId
)
{
private
int
getFileTransferNotificationId
(
android
.
net
.
Uri
path
,
Stri
ng
dataTransferId
)
{
return
(
NOTIF_FILE_TRANSFER
+
path
.
toString
()
+
dataTransferId
).
hashCode
();
}
...
...
ring-android/app/src/main/java/cx/ring/tv/conversation/TvConversationAdapter.java
View file @
79b6d163
...
...
@@ -632,13 +632,15 @@ public class TvConversationAdapter extends RecyclerView.Adapter<TvConversationVi
}
context
.
startService
(
new
Intent
(
DRingService
.
ACTION_FILE_ACCEPT
)
.
setClass
(
context
.
getApplicationContext
(),
DRingService
.
class
)
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
file
.
getDaemonId
()));
.
putExtra
(
DRingService
.
KEY_MESSAGE_ID
,
file
.
getMessageId
())
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
file
.
getFileId
()));
});
viewHolder
.
btnRefuse
.
setOnClickListener
(
v
->
{
Context
context
=
v
.
getContext
();
context
.
startService
(
new
Intent
(
DRingService
.
ACTION_FILE_CANCEL
)
.
setClass
(
context
.
getApplicationContext
(),
DRingService
.
class
)
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
file
.
getDaemonId
()));
.
putExtra
(
DRingService
.
KEY_MESSAGE_ID
,
file
.
getMessageId
())
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
file
.
getFileId
()));
});
}
else
{
viewHolder
.
mAnswerLayout
.
setVisibility
(
View
.
GONE
);
...
...
ring-android/app/src/main/java/cx/ring/tv/conversation/TvConversationFragment.java
View file @
79b6d163
...
...
@@ -379,7 +379,7 @@ public class TvConversationFragment extends BaseSupportFragment<ConversationPres
}
@Override
public
void
shareFile
(
File
path
)
{
public
void
shareFile
(
File
path
,
String
displayName
)
{
Context
c
=
getContext
();
if
(
c
==
null
)
return
;
...
...
@@ -400,7 +400,7 @@ public class TvConversationFragment extends BaseSupportFragment<ConversationPres
}
@Override
public
void
openFile
(
File
path
)
{
public
void
openFile
(
File
path
,
String
displayName
)
{
Context
c
=
getContext
();
if
(
c
==
null
)
return
;
...
...
@@ -807,7 +807,8 @@ public class TvConversationFragment extends BaseSupportFragment<ConversationPres
requireActivity
().
startService
(
new
Intent
(
DRingService
.
ACTION_FILE_ACCEPT
)
.
setClass
(
requireContext
(),
DRingService
.
class
)
.
setData
(
ConversationPath
.
toUri
(
accountId
,
conversationUri
))
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
transfer
.
getDaemonId
()));
.
putExtra
(
DRingService
.
KEY_MESSAGE_ID
,
transfer
.
getMessageId
())
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
transfer
.
getFileId
()));
}
@Override
...
...
@@ -815,7 +816,8 @@ public class TvConversationFragment extends BaseSupportFragment<ConversationPres
requireActivity
().
startService
(
new
Intent
(
DRingService
.
ACTION_FILE_CANCEL
)
.
setClass
(
requireContext
(),
DRingService
.
class
)
.
setData
(
ConversationPath
.
toUri
(
accountId
,
conversationUri
))
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
transfer
.
getDaemonId
()));
.
putExtra
(
DRingService
.
KEY_MESSAGE_ID
,
transfer
.
getMessageId
())
.
putExtra
(
DRingService
.
KEY_TRANSFER_ID
,
transfer
.
getFileId
()));
}
}
ring-android/app/src/main/java/cx/ring/utils/AndroidFileUtils.java
View file @
79b6d163
...
...
@@ -52,6 +52,7 @@ import java.util.Locale;
import
androidx.annotation.NonNull
;
import
net.jami.model.Conversation
;
import
net.jami.utils.FileUtils
;
import
io.reactivex.Completable
;
...
...
@@ -317,6 +318,22 @@ public class AndroidFileUtils {
}).
subscribeOn
(
Schedulers
.
io
());
}
public
static
@NonNull
Single
<
File
>
getFileToSend
(
@NonNull
Context
context
,
@NonNull
Conversation
conversation
,
@NonNull
Uri
uri
)
{
ContentResolver
contentResolver
=
context
.
getContentResolver
();
File
cacheDir
=
context
.
getCacheDir
();
return
Single
.
fromCallable
(()
->
{
File
file
=
new
File
(
cacheDir
,
getFilename
(
contentResolver
,
uri
));
try
(
InputStream
inputStream
=
contentResolver
.
openInputStream
(
uri
);
FileOutputStream
output
=
new
FileOutputStream
(
file
))
{
if
(
inputStream
==
null
)
throw
new
FileNotFoundException
();
net
.
jami
.
utils
.
FileUtils
.
copyFile
(
inputStream
,
output
);
output
.
flush
();
}
return
file
;
}).
subscribeOn
(
Schedulers
.
io
());
}
public
static
Completable
moveToUri
(
@NonNull
ContentResolver
cr
,
@NonNull
File
input
,
@NonNull
Uri
outUri
)
{
return
Completable
.
fromAction
(()
->
{
try
(
InputStream
inputStream
=
new
FileInputStream
(
input
);
...
...
@@ -363,7 +380,6 @@ public class AndroidFileUtils {
public
static
File
getConversationDir
(
Context
context
,
String
conversationId
)
{
File
conversationsDir
=
getFilePath
(
context
,
"conversation_data"
);
if
(!
conversationsDir
.
exists
())
conversationsDir
.
mkdir
();
...
...
@@ -374,9 +390,28 @@ public class AndroidFileUtils {
return
conversationDir
;
}
public
static
File
getConversationDir
(
Context
context
,
String
accountId
,
String
conversationId
)
{
File
conversationsDir
=
getFilePath
(
context
,
"conversation_data"
);
if
(!
conversationsDir
.
exists
())
conversationsDir
.
mkdir
();
File
accountDir
=
new
File
(
conversationsDir
,
accountId
);
if
(!
accountDir
.
exists
())
accountDir
.
mkdir
();
File
conversationDir
=
new
File
(
accountDir
,
conversationId
);
if
(!
conversationDir
.
exists
())
conversationDir
.
mkdir
();
return
conversationDir
;
}
public
static
File
getConversationPath
(
Context
context
,
String
conversationId
,
String
name
)
{
return
new
File
(
getConversationDir
(
context
,
conversationId
),
name
);
}
public
static
File
getConversationPath
(
Context
context
,
String
accountId
,
String
conversationId
,
String
name
)
{
return
new
File
(
getConversationDir
(
context
,
accountId
,
conversationId
),
name
);
}
public
static
File
getTempPath
(
Context
context
,
String
conversationId
,
String
name
)
{
File
conversationsDir
=
getCachePath
(
context
,
"conversation_data"
);
...
...
ring-android/app/src/main/java/cx/ring/utils/ContentUriHandler.java
View file @
79b6d163
...
...
@@ -24,12 +24,13 @@ import android.content.Context;
import
android.content.res.Resources
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.util.Log
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.core.content.FileProvider
;
import
net.jami.utils.FileUtils
;
import
net.jami.utils.Log
;
import
java.io.File
;
...
...
@@ -75,28 +76,33 @@ public class ContentUriHandler {
}
public
static
Uri
getUriForFile
(
@NonNull
Context
context
,
@NonNull
String
authority
,
@NonNull
File
file
)
{
if
(
HUAWEI_MANUFACTURER
.
equalsIgnoreCase
(
Build
.
MANUFACTURER
))
{
try
{
return
FileProvider
.
getUriForFile
(
context
,
authority
,
file
);
}
catch
(
IllegalArgumentException
e
)
{
return
getUriForFile
(
context
,
authority
,
file
,
null
);
}
public
static
Uri
getUriForFile
(
@NonNull
Context
context
,
@NonNull
String
authority
,
@NonNull
File
file
,
@Nullable
String
displayName
)
{
try
{
return
displayName
==
null
?
FileProvider
.
getUriForFile
(
context
,
authority
,
file
)
:
FileProvider
.
getUriForFile
(
context
,
authority
,
file
,
displayName
);
}
catch
(
IllegalArgumentException
e
)
{
if
(
HUAWEI_MANUFACTURER
.
equalsIgnoreCase
(
Build
.
MANUFACTURER
))
{
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
N
)
{
net
.
jami
.
utils
.
Log
.
w
(
TAG
,
"Returning Uri.fromFile to avoid Huawei 'external-files-path' bug for pre-N devices"
,
e
);
Log
.
w
(
TAG
,
"Returning Uri.fromFile to avoid Huawei 'external-files-path' bug for pre-N devices"
,
e
);
return
Uri
.
fromFile
(
file
);
}
else
{
net
.
jami
.
utils
.
Log
.
w
(
TAG
,
"ANR Risk -- Copying the file the location cache to avoid Huawei 'external-files-path' bug for N+ devices"
,
e
);
Log
.
w
(
TAG
,
"ANR Risk -- Copying the file the location cache to avoid Huawei 'external-files-path' bug for N+ devices"
,
e
);
// Note: Periodically clear this cache
final
File
cacheFolder
=
new
File
(
context
.
getCacheDir
(),
HUAWEI_MANUFACTURER
);
final
File
cacheLocation
=
new
File
(
cacheFolder
,
file
.
getName
());
if
(
FileUtils
.
copyFile
(
file
,
cacheLocation
))
{
Log
.
i
(
TAG
,
"Completed Android N+ Huawei file copy. Attempting to return the cached file"
);
return
FileProvider
.
getUriForFile
(
context
,
authority
,
cacheLocation
);
return
displayName
==
null
?
FileProvider
.
getUriForFile
(
context
,
authority
,
cacheLocation
)
:
FileProvider
.
getUriForFile
(
context
,
authority
,
cacheLocation
,
displayName
);
}
net
.
jami
.
utils
.
Log
.
e
(
TAG
,
"Failed to copy the Huawei file. Re-throwing exception"
);
Log
.
e
(
TAG
,
"Failed to copy the Huawei file. Re-throwing exception"
);
throw
new
IllegalArgumentException
(
"Huawei devices are unsupported for Android N"
);
}
}
else
{
throw
e
;
}
}
else
{
return
FileProvider
.
getUriForFile
(
context
,
authority
,
file
);
}
}
}
ring-android/app/src/main/res/layout/item_conv_file_me.xml
View file @
79b6d163
...
...
@@ -141,7 +141,7 @@
android:layout_weight=
"0.5"
android:background=
"?attr/selectableItemBackground"
android:gravity=
"center"
android:text=
"@string/
accept
"
android:text=
"@string/
file_download
"
android:textColor=
"@color/color_primary_dark"
/>
</LinearLayout>
...
...
ring-android/app/src/main/res/layout/item_conv_file_peer.xml
View file @
79b6d163
...
...
@@ -148,7 +148,7 @@
android:layout_weight=
"0.5"
android:background=
"?attr/selectableItemBackground"
android:gravity=
"center"
android:text=
"@string/
accept
"
android:text=
"@string/
file_download
"
android:textColor=
"@color/color_primary_dark"
/>
</LinearLayout>
...
...
ring-android/app/src/main/res/values/strings.xml
View file @
79b6d163
...
...
@@ -241,8 +241,8 @@ along with this program; if not, write to the Free Software
<string
name=
"conversation_info_contact_you"
>
You
</string>
<string
name=
"conversation_members"
>
Members
</string>
<string
name=
"conversation_preference_color"
>
C
hange c
onversation color
</string>
<string
name=
"conversation_preference_emoji"
>
C
hange c
onversation emoji
</string>
<string
name=
"conversation_preference_color"
>
Conversation color
</string>
<string
name=
"conversation_preference_emoji"
>
Conversation emoji
</string>
<string
name=
"conversation_type_contact"
>
Jami contact
</string>
<string
name=
"conversation_type_private"
>
Private swarm
</string>
<string
name=
"conversation_type_group"
>
Group swarm
</string>
...
...
@@ -337,6 +337,7 @@ along with this program; if not, write to the Free Software
<string
name=
"file_transfer_status_timed_out"
>
timed out
</string>
<string
name=
"file_saved_in"
>
File saved in %s
</string>
<string
name=
"file_saved_successfully"
>
File saved successfully
</string>
<string
name=
"file_download"
>
Download
</string>
<string
name=
"no_space_left_on_device"
>
No space left on device
</string>
<string
name=
"title_media_viewer"
>
Media viewer
</string>
<string
name=
"menu_file_open"
>
Open file
</string>
...
...
ring-android/libringclient/src/main/java/net/jami/conversation/ConversationPresenter.java
View file @
79b6d163
...
...
@@ -39,6 +39,7 @@ import net.jami.services.DeviceRuntimeService;
import
net.jami.services.HardwareService
;
import
net.jami.services.PreferencesService
;
import
net.jami.services.VCardService
;
import
net.jami.utils.FileUtils
;
import
net.jami.utils.Log
;
import
net.jami.utils.StringUtils
;
import
net.jami.utils.Tuple
;
...
...
@@ -307,28 +308,24 @@ public class ConversationPresenter extends RootPresenter<ConversationView> {
public
void
saveFile
(
Interaction
interaction
)
{
DataTransfer
transfer
=
(
DataTransfer
)
interaction
;
String
fileAbsolutePath
=
getDeviceRuntimeService
().
getConversationPath
(
mConversation
.
getUri
().
getRawRingId
(),
transfer
.
getStoragePath
()
)
getConversationPath
(
transfer
)
.
getAbsolutePath
();
getView
().
startSaveFile
(
transfer
,
fileAbsolutePath
);
}
public
void
shareFile
(
Interaction
interaction
)
{
DataTransfer
file
=
(
DataTransfer
)
interaction
;
File
path
=
getDeviceRuntimeService
().
getConversationPath
(
mConversation
.
getUri
().
getRawRingId
(),
file
.
getStoragePath
()
);
getView
().
shareFile
(
path
);
File
path
=
getDeviceRuntimeService
().
getConversationPath
(
file
);
getView
().
shareFile
(
path
,
file
.
getDisplayName
()
);
}
public
void
openFile
(
Interaction
interaction
)
{
DataTransfer
file
=
(
DataTransfer
)
interaction
;
File
path
=
getDeviceRuntimeService
().
getConversationPath
(
mConversation
.
getUri
().
getRawRingId
(),
file
.
getStoragePath
()
);
getView
().
openFile
(
path
);
File
path
=
getDeviceRuntimeService
().
getConversationPath
(
file
);
getView
().
openFile
(
path
,
file
.
getDisplayName
()
);
}
public
void
acceptFile
(
DataTransfer
transfer
)
{
if
(!
getDeviceRuntimeService
().
hasWriteExternalStoragePermission
())
{
getView
().
askWriteExternalStoragePermission
();
return
;
}
getView
().
acceptFile
(
mConversation
.
getAccountId
(),
mConversationUri
,
transfer
);
}
...
...
ring-android/libringclient/src/main/java/net/jami/conversation/ConversationView.java