-
-
Notifications
You must be signed in to change notification settings - Fork 10.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support drag & drop file to device /sdcard #226
Conversation
Ping #128. Thank you for your contribution. I cannot test for now (I'm on a phone), but this will block the main thread (and freeze the UI) during the file transfer. The execution+wait must be done on a separate thread. I suggest to generalize the installer so that it can also handle file transfer requests in addition to apk installation requests. |
Hi, @rom1v Thank you for your advice. Regards. |
24e95e9
to
57e42ac
Compare
Hi, @rom1v I have integrated file transfer into installer.
Please contact me, if you have any questions or concerns. Thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, I pushed your first commit.
(see inline comments)
app/src/file_handler.c
Outdated
file_queue_take(&file_handler->queue, ¤t_file); | ||
#endif | ||
LOGI("Processing %s...", current_file); | ||
if (is_apk(current_file)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this should be an explicit request from the caller (there would be a queue of requests, having a type which can take two values, for example INSTALL_APK
or PUSH_FILE
).
This test would be in case SDL_DROPFILE
. Or better (I think): install an apk on dropfile (as it is), and push a file on Ctrl+dropfile (so that it will be possible to push apk). What do you think?
This could be done separately though. Tell me if you want to do this, otherwise I can do it later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, @rom1v
Give a type to every request is a good idea!
However, I think that push an apk without installing it make no sense. When do we need to just push an apk on the device and install it later?
Thank you for your time and effort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems weird to be able to push any file except a specific type. One may want to use its device as an "usb key", and store apk to copy them somewhere afterwards.
It's not very important though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, @rom1v
Push an apk without installing it is an rare case. I don't think that break a good design because of unusual situations is a good idea. We should remain intuitive and convenient method (simply drag & drop) for user. Therefore, I propose these behavior:
- Install apk (common case, just drag & drop)
- Push file (common case, just drag & drop)
- Push apk (rare case, ctrl + drag & drop)
What do you think?
Regards!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, so for simplicity, just forget 3. 😉
app/src/file_handler.c
Outdated
LOGI("Processing %s...", current_file); | ||
if (is_apk(current_file)) { | ||
process = adb_install(file_handler->serial, current_file); | ||
strncpy(cmd, "adb install", sizeof(cmd)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could declare cmd
as const char *
, then just:
cmd = "adb install";
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do
@@ -0,0 +1,195 @@ | |||
#include "file_handler.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<nitpick>
filehandler.c
/filehandler.h
for "consistency" with the other files (but still with _
for the structure). That's not a great convention, but at least it would be more consistent 😉
</nitpick>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a good idea. But I will do it to maintain consistency.
Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, it's weird. Don't do it, I will rename the other files instead.
Signed-off-by: npes87184 <[email protected]>
Signed-off-by: npes87184 <[email protected]>
57e42ac
to
ddc9f58
Compare
Hi, @rom1v I have pushed commits based on review. Hope you will like this change. Regards! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hope you will like this change.
Yes, thank you, great work 👍
I commented inline for requesting some fixes and suggesting several minor changes.
To avoid many roundtrips, here is a diff of the changes I suggest (the reasons are hopefully given in my inline comments on this PR). If you agree with them, I can push your commits including these changes.
diff --git a/app/src/file_handler.c b/app/src/file_handler.c
index 4dc23ce..5feb008 100644
--- a/app/src/file_handler.c
+++ b/app/src/file_handler.c
@@ -6,12 +6,27 @@
#include "lockutil.h"
#include "log.h"
+struct request {
+ file_handler_action_t action;
+ const char *file;
+};
+
+struct request *request_new(file_handler_action_t action, const char *file) {
+ struct request *req = SDL_malloc(sizeof(*req));
+ if (!req) {
+ return NULL;
+ }
+ req->action = action;
+ req->file = file;
+ return req;
+}
+
void request_free(struct request *req) {
if (!req) {
return;
}
- SDL_free(req->file);
- free(req);
+ SDL_free((void *) req->file);
+ SDL_free((void *) req);
}
SDL_bool request_queue_is_empty(const struct request_queue *queue) {
@@ -105,9 +120,10 @@ static process_t push_file(const char *serial, const char *file) {
return adb_push(serial, file, DEVICE_SDCARD_PATH);
}
-SDL_bool file_handler_add_request(struct file_handler *file_handler, const char *file, req_action_t action) {
+SDL_bool file_handler_request(struct file_handler *file_handler,
+ file_handler_action_t action,
+ const char *file) {
SDL_bool res;
- struct request *req = (struct request *) malloc(sizeof(struct request));
// start file_handler if it's used for the first time
if (!file_handler->initialized) {
@@ -117,13 +133,11 @@ SDL_bool file_handler_add_request(struct file_handler *file_handler, const char
file_handler->initialized = SDL_TRUE;
}
- LOGI("Adding request %s", file);
- req->file = SDL_strdup(file);
- req->action = action;
- if (action == INSTALL_APK) {
- req->func = install_apk;
- } else {
- req->func = push_file;
+ LOGI("Request to %s %s", action == ACTION_INSTALL_APK ? "install" : "push", file);
+ struct request *req = request_new(action, file);
+ if (!req) {
+ LOGE("Could not create request");
+ return SDL_FALSE;
}
mutex_lock(file_handler->mutex);
@@ -150,30 +164,37 @@ static int run_file_handler(void *data) {
break;
}
struct request *req;
- process_t process;
- const char *cmd;
#ifdef BUILD_DEBUG
bool non_empty = request_queue_take(&file_handler->queue, &req);
SDL_assert(non_empty);
#else
request_queue_take(&file_handler->queue, &req);
#endif
- LOGI("Processing %s...", req->file);
- process = req->func(file_handler->serial, req->file);
+ process_t process;
+ if (req->action == ACTION_INSTALL_APK) {
+ LOGI("Installing %s...", req->file);
+ process = install_apk(file_handler->serial, req->file);
+ } else {
+ LOGI("Pushing %s...", req->file);
+ process = push_file(file_handler->serial, req->file);
+ }
file_handler->current_process = process;
mutex_unlock(file_handler->mutex);
- if (req->action == INSTALL_APK) {
- cmd = "adb install";
+ if (req->action == ACTION_INSTALL_APK) {
+ if (process_check_success(process, "adb install")) {
+ LOGI("%s successfully installed", req->file);
+ } else {
+ LOGE("Failed to install %s", req->file);
+ }
} else {
- cmd = "adb push";
+ if (process_check_success(process, "adb push")) {
+ LOGI("%s successfully pushed to /sdcard/", req->file);
+ } else {
+ LOGE("Failed to push %s to /sdcard/", req->file);
+ }
}
- if (process_check_success(process, cmd)) {
- LOGI("Process %s successfully", req->file);
- } else {
- LOGE("Failed to process %s", req->file);
- }
request_free(req);
}
return 0;
diff --git a/app/src/file_handler.h b/app/src/file_handler.h
index 39dbf02..375db29 100644
--- a/app/src/file_handler.h
+++ b/app/src/file_handler.h
@@ -9,15 +9,9 @@
#define REQUEST_QUEUE_SIZE 16
typedef enum {
- INSTALL_APK = 0,
- PUSH_FILE,
-} req_action_t;
-
-struct request {
- process_t (*func)(const char *, const char *);
- char *file;
- req_action_t action;
-};
+ ACTION_INSTALL_APK,
+ ACTION_PUSH_FILE,
+} file_handler_action_t;
struct request_queue {
struct request *reqs[REQUEST_QUEUE_SIZE];
@@ -43,6 +37,8 @@ SDL_bool file_handler_start(struct file_handler *file_handler);
void file_handler_stop(struct file_handler *file_handler);
void file_handler_join(struct file_handler *file_handler);
-SDL_bool file_handler_add_request(struct file_handler *file_handler, const char *filename, req_action_t action);
+SDL_bool file_handler_request(struct file_handler *file_handler,
+ file_handler_action_t action,
+ const char *file);
#endif
diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c
index 1993d77..cee4e12 100644
--- a/app/src/scrcpy.c
+++ b/app/src/scrcpy.c
@@ -56,7 +56,7 @@ static int event_watcher(void *data, SDL_Event *event) {
}
#endif
-static int is_apk(const char *file) {
+static SDL_bool is_apk(const char *file) {
const char *ext = strrchr(file, '.');
return ext && !strcmp(ext, ".apk");
}
@@ -109,13 +109,16 @@ static SDL_bool event_loop(void) {
case SDL_MOUSEBUTTONUP:
input_manager_process_mouse_button(&input_manager, &event.button);
break;
- case SDL_DROPFILE:
+ case SDL_DROPFILE: {
+ file_handler_action_t action;
if (is_apk(event.drop.file)) {
- file_handler_add_request(&file_handler, event.drop.file, INSTALL_APK);
+ action = ACTION_INSTALL_APK;
} else {
- file_handler_add_request(&file_handler, event.drop.file, PUSH_FILE);
+ action = ACTION_PUSH_FILE;
}
+ file_handler_request(&file_handler, action, event.drop.file);
break;
+ }
}
}
return SDL_FALSE;
return; | ||
} | ||
SDL_free(req->file); | ||
free(req); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SDL_free((void *) req)
@@ -56,6 +56,11 @@ static int event_watcher(void *data, SDL_Event *event) { | |||
} | |||
#endif | |||
|
|||
static int is_apk(const char *file) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return SDL_bool
} req_action_t; | ||
|
||
struct request { | ||
process_t (*func)(const char *, const char *); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either store func+file or action+file, but not both. Since the action is useful later (for error messages), I suggest to remove func.
|
||
SDL_bool file_handler_add_request(struct file_handler *file_handler, const char *file, req_action_t action) { | ||
SDL_bool res; | ||
struct request *req = (struct request *) malloc(sizeof(struct request)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check malloc failure
|
||
SDL_bool file_handler_add_request(struct file_handler *file_handler, const char *file, req_action_t action) { | ||
SDL_bool res; | ||
struct request *req = (struct request *) malloc(sizeof(struct request)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not leak req
if file_handler_start()
fails
PUSH_FILE, | ||
} req_action_t; | ||
|
||
struct request { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
request
is used only internally, it could be moved to file_handler.c
.
I'll do the same later with request_queue
.
EDIT: ah no, request_queue
is used by file_handler
in the .h
.
void file_handler_stop(struct file_handler *file_handler); | ||
void file_handler_join(struct file_handler *file_handler); | ||
|
||
SDL_bool file_handler_add_request(struct file_handler *file_handler, const char *filename, req_action_t action); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's subjective, but I would reverse action and file (we request an action, and pass its parameter afterwards).
typedef enum { | ||
INSTALL_APK = 0, | ||
PUSH_FILE, | ||
} req_action_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since they are actions associated by the file_handler
, I would prefer something like file_handler_action_t
(especially once request
is moved to the .c
).
file_handler->initialized = SDL_TRUE; | ||
} | ||
|
||
LOGI("Adding request %s", file); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should log the action too.
#else | ||
request_queue_take(&file_handler->queue, &req); | ||
#endif | ||
LOGI("Processing %s...", req->file); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Different log messages for install and push would be better for the user.
Hi, It is awesome, go ahead! Thank you for your efforts. |
support drag & drop file to device /sdcard
Rename foobar.ext to foo_bar.ext. <#226 (comment)>
Rename foobar.ext to foo_bar.ext. <#226 (comment)>
Hi, folks
With drop & drag file to device /sdcard, it will be very convenient to app developer to test app which need some file in the device.
In this patch, if people drop & drag an apk file, it will remain the same behavior. Otherwise, it will push the file to /sdcard.
Thanks.
Signed-off-by: npes87184 [email protected]