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

Added option to share and import Contacts #25

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Instantium
Copy link

This PR adds the option to share and import Contacts.

To share a contact open it in the Details View and press the share button. A zip file is created that can be shared via messaging apps or stored on the phone.
To import contacts, go to the contact list view and press import. Chose the zip file and the contact is imported.

This is useful as a backup, to share the same contacts as your partner or to give distant family members the app and let them record themselves.

@pserwylo
Copy link
Member

Oh wow, this sounds wonderful! I love the user experience you have outlined here, and would love to get this in. Please let me know if there is anything you need while working on this, and I'd be happy to help.

@Instantium Instantium marked this pull request as ready for review September 24, 2023 12:26
@Instantium
Copy link
Author

I need just a review :D Forgot to make the draft into an actual PR.

@pserwylo
Copy link
Member

Ah, not a problem. Cool.

Quick test shows that it is missing an ic_share drawable. I added that via the Android Studio "File -> New -> Vector Asset" dialog, which worked fine.

After this, my emulator crashed when trying to share because it does not have an application able to share .zip files:

E  FATAL EXCEPTION: main
Process: com.serwylo.babyphone, PID: 16005
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.SEND typ=application/zip flg=0x1 clip={application/zip U:content://com.serwylo.babyphone.fileprovider/contact_photos/Another%20one.zip} (has extras) }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1937)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1616)
at android.app.Activity.startActivityForResult(Activity.java:4487)
at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:728)
at android.app.Activity.startActivityForResult(Activity.java:4445)
at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:709)
at android.app.Activity.startActivity(Activity.java:4806)
at android.app.Activity.startActivity(Activity.java:4774)
at com.serwylo.babyphone.editcontact.EditContactActivity$onShareContact$1.invokeSuspend(EditContactActivity.kt:178)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at com.serwylo.babyphone.editcontact.EditContactActivity.onShareContact(EditContactActivity.kt:171)
at com.serwylo.babyphone.editcontact.EditContactActivity.onOptionsItemSelected(EditContactActivity.kt:164)

Looks like we can query for if anything is available to share the zip file, and if not, show a Toast or something with a couple of lines: https://stackoverflow.com/a/29994483.

I thought it might not matter at all in practice, because most people have something capable of sending files. So I installed F-Droid on my emulator, then tried:

  • QKSMS (Full featured SMS/MMS app) - this didn't help, doesn't seem to be able to handle files.
  • k9mail - also didn't seem to work (kind of assumed this one would allow it to be attached as a file).

When I installed a file manager (Amaze), it worked, allowing me to choose a file to save to.

On the one hand, most phones will have Bluetooth (emulators don't) and so this in practice may not be an issue. On the other hand, it may be more prevalent then we thought. if so, perhapse renaming the feature to "Export" and choosing the opposite icon to the import icon you use from main settings screen? Or if we really think that it will work most of the time, then lets go ahead, but perhaps add the check to show an error Toast if nothing is available.

@@ -231,6 +239,107 @@ class EditContactViewModel(
}
}

fun shareContact(): Uri {
val fileName = contact.name.ifEmpty { contact.id.toString() }
val zipFile = File(context.getExternalFilesDir("Contacts"), "$fileName.zip")
Copy link
Member

Choose a reason for hiding this comment

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

Do you mind if we change this to "$fileName.babyphone.zip"? The rationale is that in the future, I'd love to add an <intent-filter> to the app to listen for when people open such files in a file browser, or even downloading them from the internet. If it is just .zip with the contact name/id, then we would have to listen to all .zip files, which may provide a bad experience for people who want most .zip files to open in an archive manager.

Another way to future proof it would be to think about how one might allow multiple contacts to be put into a single zip file (again, imagine downloading a .zip file from online that contained 6 contacts). However, I don't think anything needs to change here. Rather, we could add a .json file in the zip file in the future which specifies which photos/sound files belong to each contact within the zip.

Having said that, while that is forwards-compatible, it is not backwards-compatible. One way to make this backwards-compatible would be to put the photo + sounds into a folder within the .zip file. When importing, open the first folder in the zip file.

Then, if in the future there is a zip file with multiple folders in it, old versions of the app will work just fine, and new versions will be able to import multiple contacts from the zip file. This would allow us to publish bundles of contacts online via GitHub pages in this repo or a sister repo, where people can download, I dunno, "Kittens and Puppies", or other quirky packages.

Copy link
Author

Choose a reason for hiding this comment

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

I like your ideas! 👍
Especially exporting multiple contacts at once. Right now I have to share each contact individually with my partner.

I will change the file name to be compatible with a future intent-filter.

@Instantium
Copy link
Author

That's embarrassing. I will add the share icon. Also I will add the check if there are apps that can handle the zip file.
I would suggest that we stick with the Toast for now and if it is a bigger problem, we can try something else like the "export" option that you mentioned in the else branch of that check.

@pserwylo
Copy link
Member

Hi @Instantium, hope all is well. Could I please enquire as to whether you have the time to work on the items discussed above? It is okay if not, just let me know and I'd be happy to take over to get this over and implement the couple of tweaks we discussed to get this over the line.

@Instantium
Copy link
Author

Hey, I am sorry. I still have this on my TODO-list but it got pushed down again and again. Feel free to take this over.

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.

3 participants