Skip to content
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

Mobile (Android) save dialog #2077

Merged
merged 8 commits into from Mar 17, 2021
Merged

Mobile (Android) save dialog #2077

merged 8 commits into from Mar 17, 2021

Conversation

howeyc
Copy link
Contributor

@howeyc howeyc commented Mar 10, 2021

Description:

Adds file save support for android. The dex file is generated using the GoNativeActivity.java from my pull-request against the 'mobile' repository.

Fixes #2076

I don't have a Mac so I have no idea how IOS would work. There are just empty stubs there.

Checklist:

  • Tests included.
  • Lint and formatter run with no errors.
  • Tests all pass.

Where applicable:

  • Public APIs match existing style.
  • Any breaking changes have a deprecation path or have been discussed.

@howeyc howeyc changed the base branch from master to develop March 10, 2021 20:20
Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. I think we need to land the PR to mobile dep first otherwise the generated dex file is rather arbitrary.

Additionally there is a commented out type assertion for the Writer interface inside internal/driver/gomobile that should be enabled to ensure test that this will advertise as writeable.

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So close.
If you can update this typo, update the fyne-io/mobile version and re-generate dex I think we are good to go :).

@@ -34,6 +32,19 @@ func (m *mobileFileRepo) CanRead(u fyne.URI) (bool, error) {
func (m *mobileFileRepo) Destroy(string) {
}

func (m *mobileFileRepo) CanWrite(u fyne.URI) (bool, error) {
return true, nil // TODO check a file can be read
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a copy-paste issue in comment

@howeyc
Copy link
Contributor Author

howeyc commented Mar 12, 2021

The dex here is what I did by taking latest GoNative java and running a manual edited gendex to use that file. I'm not sure how to do using vendor or however it's usually done.

@andydotxyz
Copy link
Member

Just run "go mod vendor" and commit the module/vendor changes.
As the mobile repo has changed I guess you'll need to re-run gendex as well.

@howeyc
Copy link
Contributor Author

howeyc commented Mar 16, 2021

This pull request does have the updated dex.go file as a result of running gendex. You can see it in the change file list.

Just an FYI in case you are waiting on me.

@andydotxyz
Copy link
Member

Apologies if I’m wrong, but the date stamps make it look like the generated dex was created before mime parameters were added. Does it not need to be updated again?

@howeyc
Copy link
Contributor Author

howeyc commented Mar 16, 2021

That's my "fault" for updating the dex.go as I was making changes I guess. I manually generated with up-to-date java file as I was making commits.

So for instance you'll see the dex.go file has changes along with the other changes in the mime commit.

@andydotxyz
Copy link
Member

Goodness, no, nothing wrong here except I missed that dex change, sorry. Will test again in the morning and we should be good.

@andydotxyz
Copy link
Member

Running on my Android phone it seems to crash. Do I need to add anything to the apk for this new code to work?

03-17 12:10:50.935 21957 22810 F io.fyne.demo: java_vm_ext.cc:578] JNI DETECTED ERROR IN APPLICATION: thread Thread[18,tid=22810,Runnable,Thread*=0x729e98b8e0,peer=0x12d01dc8,"Thread-8"] using JNI after critical get
03-17 12:10:50.935 21957 22810 F io.fyne.demo: java_vm_ext.cc:578]     in call to CallVoidMethod
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677] Runtime aborting...
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677] Dumping all threads without mutator lock held
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677] All threads:
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677] DALVIK THREADS (18):
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677] "Thread-8" prio=10 tid=18 Runnable
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | group="" sCount=0 dsCount=0 flags=0 obj=0x12d01dc8 self=0x729e98b8e0
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | sysTid=22810 nice=-10 cgrp=default sched=0/0 handle=0x7078afdcc0
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | state=R schedstat=( 111049529 21631033 2976 ) utm=5 stm=5 core=6 HZ=100
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | stack=0x7078a06000-0x7078a08000 stackSize=995KB
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | held mutexes= "abort lock" "mutator lock"(shared held)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #00 pc 00000000004af964  /apex/com.android.art/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+140)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #01 pc 00000000005bf194  /apex/com.android.art/lib64/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool, BacktraceMap*, bool) const+372)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #02 pc 00000000005dc734  /apex/com.android.art/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+924)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #03 pc 00000000005d65a4  /apex/com.android.art/lib64/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+532)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #04 pc 00000000005d5724  /apex/com.android.art/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool)+1876)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #05 pc 000000000056f184  /apex/com.android.art/lib64/libart.so (art::Runtime::Abort(char const*)+1876)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #06 pc 0000000000013ab0  /system/lib64/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_3::__invoke(char const*)+80)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #07 pc 0000000000013090  /system/lib64/libbase.so (android::base::LogMessage::~LogMessage()+320)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #08 pc 0000000000392ea8  /apex/com.android.art/lib64/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+2608)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #09 pc 0000000000392f24  /apex/com.android.art/lib64/libart.so (art::JavaVMExt::JniAbortV(char const*, char const*, std::__va_list)+108)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #10 pc 00000000003849ec  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::AbortF(char const*, ...)+148)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #11 pc 0000000000383440  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckPossibleHeapValue(art::ScopedObjectAccess&, char, art::(anonymous namespace)::JniValueType)+2976)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #12 pc 000000000038212c  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::(anonymous namespace)::JniValueType*)+612)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #13 pc 000000000038797c  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::CheckCallArgs(art::ScopedObjectAccess&, art::(anonymous namespace)::ScopedCheck&, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, art::InvokeType, art::(anonymous namespace)::VarArgs const*)+132)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #14 pc 00000000003868b4  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, std::__va_list, art::Primitive::Type, art::InvokeType)+748)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #15 pc 0000000000374ce0  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::CallVoidMethod(_JNIEnv*, _jobject*, _jmethodID*, ...)+152)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #16 pc 0000000000473ea0  /data/app/~~SaECgm2ow394AYsfrYjOYQ==/io.fyne.demo-9uf4vqg42SJpXE18b7-OkA==/lib/arm64/libfyne_demo.so (writeStream+248)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   (no managed stack frames)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677] 
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677] "main" prio=10 tid=1 Native
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | group="" sCount=1 dsCount=0 flags=1 obj=0x733dd968 self=0x729e96e010
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | sysTid=21957 nice=-10 cgrp=default sched=0/0 handle=0x74265c8500
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | state=S schedstat=( 340777202 27483531 280 ) utm=22 stm=11 core=5 HZ=100
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | stack=0x7ffc127000-0x7ffc129000 stackSize=8192KB
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   | held mutexes=
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   native: #00 pc 000000000022301c  /data/app/~~SaECgm2ow394AYsfrYjOYQ==/io.fyne.demo-9uf4vqg42SJpXE18b7-OkA==/lib/arm64/libfyne_demo.so (runtime.futex+28)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at org.golang.app.GoNativeActivity.filePickerReturned(Native method)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at org.golang.app.GoNativeActivity.onActivityResult(GoNativeActivity.java:271)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.app.Activity.dispatchActivityResult(Activity.java:8541)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.app.ActivityThread.deliverResults(ActivityThread.java:5499)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.app.ActivityThread.handleSendResult(ActivityThread.java:5547)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.os.Handler.dispatchMessage(Handler.java:106)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.os.Looper.loop(Looper.java:246)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at android.app.ActivityThread.main(ActivityThread.java:8506)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at java.lang.reflect.Method.invoke(Native method)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
03-17 12:10:51.001 21957 22810 F io.fyne.demo: runtime.cc:677]   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

@andydotxyz
Copy link
Member

To actually test the code better in fyne_demo I have pushed an update to develop branch.
Please rebase onto that and test that the file write works for you from dialogs -> save tutorial.

For reference the change is this:

diff --git a/cmd/fyne_demo/tutorials/dialog.go b/cmd/fyne_demo/tutorials/dialog.go
index 54fd28d1..a829d014 100644
--- a/cmd/fyne_demo/tutorials/dialog.go
+++ b/cmd/fyne_demo/tutorials/dialog.go
@@ -67,7 +67,7 @@ func dialogScreen(win fyne.Window) fyne.CanvasObject {
                                        return
                                }
 
-                               fileSaved(writer)
+                               fileSaved(writer, win)
                        }, win)
                }),
                widget.NewButton("Folder Open", func() {
@@ -141,13 +141,18 @@ func imageOpened(f fyne.URIReadCloser) {
        showImage(f)
 }
 
-func fileSaved(f fyne.URIWriteCloser) {
+func fileSaved(f fyne.URIWriteCloser, w fyne.Window) {
        if f == nil {
                log.Println("Cancelled")
                return
        }
 
-       log.Println("Save to...", f.URI())
+       defer f.Close()
+       _, err := f.Write([]byte("Written by Fyne demo\n"))
+       if err != nil {
+               dialog.ShowError(err, w)
+       }
+       log.Println("Saved to...", f.URI())
 }
 
 func loadImage(f fyne.URIReadCloser) *canvas.Image {

@andydotxyz
Copy link
Member

This probably relates to the URI (I was writing to downloads folder) being a "content://" which I guess may create challenges?

@howeyc
Copy link
Contributor Author

howeyc commented Mar 17, 2021

I think it had something to do with how I was sending bytes through go/c/jni.

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, works well now thanks.
Just a couple of minor points inline if you could fix please then we can merge.

jmethodID write = find_method(env, streamClass, "write", "([BII)V");

jbyteArray data = (*env)->NewByteArray(env, len);
jboolean isCopy;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately some of these tabs are spaces, so messes up the indenting

@@ -17,6 +17,8 @@ github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201123143003-f2279069162d h1:WfVxpuVm
github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201123143003-f2279069162d/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/fyne-io/mobile v0.1.3-0.20210308120140-0925491569e9 h1:VNKrDC+nmsomQ8llShnBd8X8WFAr66eEwJxX5sap1oE=
github.com/fyne-io/mobile v0.1.3-0.20210308120140-0925491569e9/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY=
github.com/fyne-io/mobile v0.1.3-0.20210312180903-f9a21000f5dc h1:A5hFL3tVUfFHhVpjmLGPs8SdVIcSkTRpFMm1Vsio5+k=
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a duplicate - can you run "go mod tidy" again?

@andydotxyz
Copy link
Member

One other note, we ask if you can avoid force-pushince once a review has been started so we can avoid re-reviewing each time.

Thnks for this work, it's great - just a few minor things to polish it off.

@howeyc
Copy link
Contributor Author

howeyc commented Mar 17, 2021

Yeah, I think I didn't do the rebase quite right or something.

@andydotxyz
Copy link
Member

Yeah, I think I didn't do the rebase quite right or something.

I probably should have suggested merging instead of rebasing. Either way this is in now - thanks so much :)

@andydotxyz andydotxyz merged commit 41e95dc into fyne-io:develop Mar 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No mobile support in dialog.ShowFileSave
2 participants