share pictures across apps (#129)

* share implemented

* added test for share intent
This commit is contained in:
Ulysse Widmer 2020-05-01 09:01:13 +02:00 committed by GitHub
parent 20a2fd51ad
commit db594bbda2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 30 deletions

View File

@ -4,19 +4,27 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.longClick import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.RootMatchers import androidx.test.espresso.matcher.RootMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import com.h.pixeldroid.objects.Account import com.h.pixeldroid.objects.Account
import com.h.pixeldroid.objects.Attachment import com.h.pixeldroid.objects.Attachment
import com.h.pixeldroid.objects.Status import com.h.pixeldroid.objects.Status
import com.h.pixeldroid.testUtility.MockServer import com.h.pixeldroid.testUtility.MockServer
import org.hamcrest.CoreMatchers
import org.hamcrest.Matcher
import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -43,6 +51,7 @@ class PostTest {
Context.MODE_PRIVATE) Context.MODE_PRIVATE)
preferences.edit().putString("accessToken", "azerty").apply() preferences.edit().putString("accessToken", "azerty").apply()
preferences.edit().putString("domain", baseUrl.toString()).apply() preferences.edit().putString("domain", baseUrl.toString()).apply()
Intents.init()
} }
@Test @Test
@ -100,4 +109,62 @@ class PostTest {
).check(matches(isDisplayed())) ).check(matches(isDisplayed()))
Thread.sleep(5000) Thread.sleep(5000)
} }
@Test
fun shareTestSimplePost() {
val expectedIntent: Matcher<Intent> = IntentMatchers.hasAction(Intent.ACTION_CHOOSER)
val attachment = Attachment(
id = "12",
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
)
val post = Status(
id = "12",
account = Account(
id = "12",
username = "douze"
),
media_attachments = listOf(attachment)
)
val intent = Intent(context, PostActivity::class.java)
intent.putExtra(Status.POST_TAG, post)
ActivityScenario.launch<PostActivity>(intent)
onView(withId(R.id.postPicture)).perform(longClick())
onView(withText(R.string.share_picture)).inRoot(RootMatchers.isPlatformPopup()).perform(click())
Thread.sleep(2000)
Intents.intended(expectedIntent)
}
@Test
fun shareIntentAlbumTest() {
val expectedIntent: Matcher<Intent> = IntentMatchers.hasAction(Intent.ACTION_CHOOSER)
val attachment1 = Attachment(
id = "12",
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
)
val attachment2 = Attachment(
id = "13",
url = "https://wiki.gnugen.ch/lib/tpl/gnugen/images/logo_web.png"
)
val post = Status(
id = "12",
account = Account(
id = "12",
username = "douze"
),
media_attachments = listOf(attachment1, attachment2)
)
val intent = Intent(context, PostActivity::class.java)
intent.putExtra(Status.POST_TAG, post)
ActivityScenario.launch<PostActivity>(intent)
onView(withId(R.id.imageImageView)).perform(longClick())
onView(withText(R.string.share_picture)).inRoot(RootMatchers.isPlatformPopup()).perform(click())
Thread.sleep(2000)
Intents.intended(expectedIntent)
}
@After
fun after() {
Intents.release()
}
} }

View File

@ -51,6 +51,10 @@ class ImageFragment : Fragment() {
ImageUtils.downloadImage(requireActivity(), view.context, imgUrl) ImageUtils.downloadImage(requireActivity(), view.context, imgUrl)
true true
} }
R.id.image_popup_menu_share_picture -> {
ImageUtils.downloadImage(requireActivity(), view.context, imgUrl, share = true)
true
}
else -> false else -> false
} }
} }

View File

@ -1,9 +1,13 @@
package com.h.pixeldroid.objects package com.h.pixeldroid.objects
import android.app.Activity import android.content.ContentValues
import android.content.Context import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Typeface import android.graphics.Typeface
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri
import android.provider.MediaStore
import android.text.Spanned import android.text.Spanned
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.util.Log import android.util.Log
@ -16,15 +20,15 @@ import android.widget.LinearLayout
import android.widget.PopupMenu import android.widget.PopupMenu
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.core.content.ContextCompat.startActivity
import androidx.core.text.toSpanned import androidx.core.text.toSpanned
import androidx.core.view.drawToBitmap
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.RequestBuilder import com.bumptech.glide.RequestBuilder
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import com.h.pixeldroid.ImageFragment import com.h.pixeldroid.ImageFragment
import com.h.pixeldroid.MainActivity
import com.h.pixeldroid.R import com.h.pixeldroid.R
import com.h.pixeldroid.api.PixelfedAPI import com.h.pixeldroid.api.PixelfedAPI
import com.h.pixeldroid.fragments.feeds.PostViewHolder import com.h.pixeldroid.fragments.feeds.PostViewHolder
@ -42,7 +46,10 @@ import kotlinx.android.synthetic.main.post_fragment.view.postPager
import kotlinx.android.synthetic.main.post_fragment.view.postPicture import kotlinx.android.synthetic.main.post_fragment.view.postPicture
import kotlinx.android.synthetic.main.post_fragment.view.postTabs import kotlinx.android.synthetic.main.post_fragment.view.postTabs
import kotlinx.android.synthetic.main.post_fragment.view.profilePic import kotlinx.android.synthetic.main.post_fragment.view.profilePic
import retrofit2.http.Url
import java.io.OutputStream
import java.io.Serializable import java.io.Serializable
import java.net.URL
/* /*
Represents a status posted by an account. Represents a status posted by an account.
@ -316,6 +323,10 @@ data class Status(
downloadImage(activity, view.context, getPostUrl()!!) downloadImage(activity, view.context, getPostUrl()!!)
true true
} }
R.id.image_popup_menu_share_picture -> {
downloadImage(activity, view.context, getPostUrl()!!, share = true)
true
}
else -> false else -> false
} }
} }

View File

@ -1,19 +1,24 @@
package com.h.pixeldroid.utils package com.h.pixeldroid.utils
import android.app.DownloadManager import android.app.DownloadManager
import android.content.ContentValues
import android.content.Context import android.content.Context
import android.content.Intent
import android.database.Cursor import android.database.Cursor
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.os.Environment import android.os.Environment
import android.provider.Settings.Global.getString import android.provider.MediaStore.Images
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import com.h.pixeldroid.R import com.h.pixeldroid.R
import java.io.File import java.io.File
class ImageUtils { class ImageUtils {
companion object { companion object {
fun downloadImage(activity: FragmentActivity, context: Context, url: String) { fun downloadImage(activity: FragmentActivity, context: Context, url: String, share: Boolean = false) {
var msg = "" var msg = ""
var lastMsg = "" var lastMsg = ""
val directory = File(Environment.DIRECTORY_PICTURES) val directory = File(Environment.DIRECTORY_PICTURES)
@ -24,6 +29,7 @@ class ImageUtils {
as DownloadManager as DownloadManager
val downloadUri = Uri.parse(url) val downloadUri = Uri.parse(url)
val title = url.substring(url.lastIndexOf("/") + 1) val title = url.substring(url.lastIndexOf("/") + 1)
val ext = url.substring(url.lastIndexOf("."))
val request = DownloadManager.Request(downloadUri).apply { val request = DownloadManager.Request(downloadUri).apply {
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI
or DownloadManager.Request.NETWORK_MOBILE) or DownloadManager.Request.NETWORK_MOBILE)
@ -43,6 +49,7 @@ class ImageUtils {
downloading = false downloading = false
} }
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
if(!share) {
msg = when (status) { msg = when (status) {
DownloadManager.STATUS_FAILED -> DownloadManager.STATUS_FAILED ->
context.getString(R.string.image_download_failed) context.getString(R.string.image_download_failed)
@ -58,20 +65,34 @@ class ImageUtils {
} }
lastMsg = msg lastMsg = msg
} }
} else if (status == DownloadManager.STATUS_SUCCESSFUL) {
val icon: Bitmap = BitmapFactory.decodeFile(
Uri.parse(cursor.getString(
cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)
)).path
)
val intentShare = Intent(Intent.ACTION_SEND)
intentShare.type = "image/$ext"
val values = ContentValues()
values.put(Images.Media.TITLE, title)
values.put(Images.Media.MIME_TYPE, "image/$ext")
val uri: Uri = context.contentResolver.insert(
Images.Media.EXTERNAL_CONTENT_URI,
values
)!!
try {
val outstream = context.contentResolver.openOutputStream(uri)!!
icon.compress(Bitmap.CompressFormat.JPEG, 100, outstream)
outstream.close()
} catch(e: Exception) {
e.printStackTrace()
}
intentShare.putExtra(Intent.EXTRA_STREAM, uri)
context.startActivity(Intent.createChooser(intentShare, "Share Image"))
}
cursor.close() cursor.close()
} }
}).start() }).start()
} }
private fun statusMessage(url: String, directory: File, status: Int, context: Context): String {
return when (status) {
DownloadManager.STATUS_FAILED -> context.getString(R.string.image_download_failed)
DownloadManager.STATUS_RUNNING -> "Downloading..."
DownloadManager.STATUS_SUCCESSFUL -> "Image downloaded successfully in $directory" + File.separator + url.substring(
url.lastIndexOf("/") + 1
)
else -> ""
}
}
} }
} }

View File

@ -2,4 +2,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/image_popup_menu_save_to_gallery" <item android:id="@+id/image_popup_menu_save_to_gallery"
android:title="@string/save_to_gallery"/> android:title="@string/save_to_gallery"/>
<item android:id="@+id/image_popup_menu_share_picture"
android:title="@string/share_picture"/>
</menu> </menu>

View File

@ -49,4 +49,5 @@
<string name="image_download_failed">Download has been failed, please try again</string> <string name="image_download_failed">Download has been failed, please try again</string>
<string name="image_download_downloading">Downloading…</string> <string name="image_download_downloading">Downloading…</string>
<string name="image_download_success">Image downloaded successfully</string> <string name="image_download_success">Image downloaded successfully</string>
<string name="share_picture">Share picture...</string>
</resources> </resources>