Kotlin : How to use Branch sdk to share an image? - android

In my android app with kotlin language with IDE Android studio 4.0,
I want to share a product which have an image and some other information.
I use the Branch Sdk, I added a new module in my project.
In AndroidManifest.xml, I add the following instructions :
<meta-data android:name="io.branch.sdk.BranchKey" android:value="......" />
<intent-filter>
<data android:scheme="...app.link" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="...-app.link"
android:scheme="https" />
<!-- example-alternate domain is required for App Links when the Journeys/Web SDK and Deepviews are used inside your website. -->
<data
android:host="....test-app.link"
android:scheme="https" />
</intent-filter>
In my build.gradle, I added :
implementation project(path: ':Branch-SDK')
Let's move to kotlin code now, I add the following function :
fun prepareSharingLink(
itemID: String,
itemType: String,
imageURL: String?,
customTitle: String = ""
): BranchUniversalObject {
val canonical = itemType.plus("/").plus(itemID)
var branchUniversalObject = BranchUniversalObject()
branchUniversalObject.canonicalIdentifier = canonical
branchUniversalObject.title = customTitle
branchUniversalObject.setContentDescription("")
branchUniversalObject.setContentImageUrl(imageURL!!)
branchUniversalObject.contentMetadata.customMetadata["itemType"] = itemType
branchUniversalObject.contentMetadata.customMetadata["itemID"] = itemID
branchUniversalObject.isLocallyIndexable
branchUniversalObject.isPublicallyIndexable
branchUniversalObject.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PRIVATE)
return branchUniversalObject
}
And In the product activity, when I click on share button, I add the following code :
share.setOnClickListener {
val image = productData.mainImage
val url = this.getString(R.string.image_URL) + image
buo = Utility(this).prepareSharingLink(
productData.id.toString(),
"product",
url,
UtilityTools.getInstance().getValue(productData.name)
)
val linkProperties = LinkProperties()
val message =
if (UtilityTools.getIsAr()) "يرجى الاطلاع على هذا المنتج "
else "Check out this product"
val ss = ShareSheetStyle(this, "Check this out!", message)
.setCopyUrlStyle(
resources.getDrawable(android.R.drawable.ic_menu_send),
"Copy",
"Added to clipboard"
)
.setMoreOptionStyle(
resources.getDrawable(android.R.drawable.ic_menu_search),
"Show more"
)
.addPreferredSharingOption(SharingHelper.SHARE_WITH.FACEBOOK)
.addPreferredSharingOption(SharingHelper.SHARE_WITH.EMAIL)
.addPreferredSharingOption(SharingHelper.SHARE_WITH.MESSAGE)
.addPreferredSharingOption(SharingHelper.SHARE_WITH.HANGOUT)
.setAsFullWidthStyle(true)
.setSharingTitle("Share With")
buo.showShareSheet(this, linkProperties, ss, object : Branch.BranchLinkShareListener {
override fun onShareLinkDialogLaunched() {}
override fun onShareLinkDialogDismissed() {}
override fun onLinkShareResponse(sharedLink: String?, sharedChannel: String?, error: BranchError?) {
Log.e("LinkShared", "success")
}
override fun onChannelSelected(channelName: String) {}
})
After all this, I couldn't sharing the product detail yet,
So, How can I use Branch sdk to share this product ? And where's the problem in my code ?

Related

Oauth2 Callback URI not captured via AppLink on Android using AppAuth

I'm making an App that will use the FreeSound API, and for making certain requests I need to authenticate via Oauth2. I'm using the AuthApp Library for this purpose. I get the authorization process done, here's the code:
#Composable
fun LoginScreen(viewmodel: LoginViewModel = hiltViewModel(), context: Context) {
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val data = result.data
data?.let {
val resp = AuthorizationResponse.fromIntent(it)
val ex = AuthorizationException.fromIntent(it)
}
}
Column(modifier = Modifier.fillMaxSize()) {
Button(onClick = {
val authService = AuthorizationService(context)
val authIntent = authService.getAuthorizationRequestIntent(viewmodel.authRequest)
launcher.launch(authIntent)
}) {
Text("Authorize")
}
}
}
And this is the part defined on the view model
private val serviceConfig = AuthorizationServiceConfiguration(
Uri.parse("https://freesound.org/apiv2/oauth2/logout_and_authorize/"), // authorization endpoint
Uri.parse("https://freesound.org/apiv2/oauth2/access_token/") // token endpoint
)
private val clientId = "my_client_id"
private val redirectUri: Uri = Uri.parse("https://freesound.org/home/app_permissions/permission_granted/")
private val builder = AuthorizationRequest.Builder(
serviceConfig,
clientId,
ResponseTypeValues.CODE,
redirectUri
)
val authRequest = builder.build()
This launches the custom tab properly and I get to make the authorization, but when it comes to listen to the deeplink, it just does nothing, here's how I have defined the manifest.
<activity
android:name="com.example.app.MainActivity"
android:exported="true"
android:label="#string/app_name"
android:theme="#style/Theme.MyApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="net.openid.appauth.RedirectUriReceiverActivity"
tools:node="replace"
android:exported="true">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https"
android:host="freesound.org" android:path="/home/app_permissions/permission_granted"/>
</intent-filter>
</activity>
The redirect callback url defined on freesound is this "https://freesound.org/home/app_permissions/permission_granted/" it returns the code as a parameter on the url, but the app does not react, and I cannot change the callback from a url to a custom scheme.

Branch Deep Link does not open play store

I use Branch deep link in my android app with kotlin, I use the following link https://help.branch.io/developers-hub/docs/android-basic-integration
AndroidManifest.xml :
<application
android:name="net.app.activity.application"
android:allowBackup="false"
android:appComponentFactory="whateverString"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="false"
android:theme="#style/AppTheme"
android:usesCleartextTraffic="true"
tools:replace="android:supportsRtl,android:allowBackup,android:appComponentFactory">
<activity android:name="net.app.activity.splash.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data android:scheme="app" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<!-- Branch App Links (optional) -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent
.category.BROWSABLE" />
<data android:scheme="https" android:host="app.test-app.link" />
<data android:scheme="https" android:host="app-alternate.test-app.link" />
</intent-filter>
</activity>
<meta-data
android:name="io.branch.sdk.BranchKey"
android:value="key...." />
<meta-data
android:name="io.branch.sdk.BranchKey.test"
android:value="key...." />
<meta-data
android:name="io.branch.sdk.TestMode"
android:value="false" />
I add Branch to My ApplicationClass.java :
// Branch logging for debugging
Branch.enableLogging();
// Branch object initialization
Branch.getAutoInstance(this);
I add Branch to my lancherActivity which is SplashActivity.kt as follows :
override fun onStart() {
super.onStart()
// Branch init
Branch.sessionBuilder(this).withCallback(branchListener).withData(this.intent?.data).init()
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
this.intent = intent
// Branch reinit (in case Activity is already in foreground when Branch link is clicked)
Branch.sessionBuilder(this).withCallback(branchListener).reInit()
}
object branchListener : Branch.BranchReferralInitListener {
override fun onInitFinished(referringParams: JSONObject?, error: BranchError?) {
if (error == null) {
Log.i("BRANCH SDK", referringParams.toString())
// Retrieve deeplink keys from 'referringParams' and evaluate the values to determine where to route the user
// Check '+clicked_branch_link' before deciding whether to use your Branch routing logic
} else {
Log.e("BRANCH SDK", error.message)
}
}
}
In my app,In one of my UI, A product with all details like name, quantity, price etc...I want to share this product, I create a share button, When I click on I choose "copied to press...",I copied the Url, then I paste it in the navigator, I want that the app will be opened in the app store But I didn't get this result.
Here's my code of sharing :
shareMerchant.setOnClickListener {
val image = merchant!!.logo
val url = this.getString(R.string.image_URL) + image
buo = Utility(this).prepareSharingLink(
merchant!!.id.toString(),
"store",
url,
UtilityTools.getInstance().getValue(merchant!!.name)
)
val lp = LinkProperties()
val message =
"Check out this store on App"
val ss = ShareSheetStyle(this, "Check this out!", message)
.setCopyUrlStyle(
resources.getDrawable(android.R.drawable.ic_menu_send, this.theme),
"Copy",
"Added to clipboard"
)
.setMoreOptionStyle(
resources.getDrawable(android.R.drawable.ic_menu_search, this.theme),
"Show more"
)
.addPreferredSharingOption(SharingHelper.SHARE_WITH.EMAIL)
.addPreferredSharingOption(SharingHelper.SHARE_WITH.MESSAGE)
.addPreferredSharingOption(SharingHelper.SHARE_WITH.HANGOUT)
.setAsFullWidthStyle(true)
.setSharingTitle("Share With")
buo.showShareSheet(this, lp, ss, object : Branch.BranchLinkShareListener {
override fun onShareLinkDialogLaunched() {}
override fun onShareLinkDialogDismissed() {}
override fun onLinkShareResponse(
sharedLink: String?,
sharedChannel: String?,
error: BranchError?
) {
val metaData: java.util.HashMap<String, String> = java.util.HashMap()
if (error == null) {
metaData[Defines.Jsonkey.SharedLink.key] = sharedLink!!
} else {
metaData[Defines.Jsonkey.ShareError.key] = error.message
}
}
override fun onChannelSelected(channelName: String) {}
})
prepareSharingLink code as follows :
fun prepareSharingLink(
itemID: String,
itemType: String,
imageURL: String?,
customTitle: String = ""
): BranchUniversalObject {
val canonical = itemType.plus("/").plus(itemID)
val branchUniversalObject = BranchUniversalObject()
branchUniversalObject.canonicalIdentifier = canonical
branchUniversalObject.title = customTitle
branchUniversalObject.setContentDescription("")
branchUniversalObject.setContentImageUrl(imageURL!!)
branchUniversalObject.contentMetadata.customMetadata["itemType"] = itemType
branchUniversalObject.contentMetadata.customMetadata["itemID"] = itemID
branchUniversalObject.isLocallyIndexable
branchUniversalObject.isPublicallyIndexable
branchUniversalObject.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PRIVATE)
return branchUniversalObject
}
I want to know if I have an error or something missing in my code? And Why Branch Deep Link does not open with play store?

Android firebase: pendingDynamicLinkData always null

i'm working on email verification. Email reaches the mailbox and when the user clicks on the link it moves him to the application. When I try to get data from link in getDynamicLinks method, pendingDynamicLinkData is null. But i can get the link from intent.
Link looks like: (https://travellersystems.page.link?link=https://traveller-249409.firebaseapp.com/__/auth/action?apiKey%3DAIzaSyCrwQqjOn5v4BDdkKCZHMmmav1YEzvaq5s%26mode%3DverifyEmail%26oobCode%3D0fQfmM0UAHrdNQbUyntffzFH39GtEODVCiVfnrcD0VUAAAFtIQ0HyQ%26continueUrl%3Dhttps://travellersystems.page.link/verify?email%253Ddaniellegawiec20#gmail.com%26lang%3Dpl&apn=com.client.traveller&amv)
Here I want to get email from the continueURL.
Here i create dynamic link and i'm sending verification email to the user
val url = "https://travellersystems.page.link/verify?email=${FirebaseAuth.getInstance().currentUser?.email}"
val dynamicLink = FirebaseDynamicLinks.getInstance().createDynamicLink()
.setLink(Uri.parse(url))
.setDomainUriPrefix("travellersystems.page.link/")
.setAndroidParameters(DynamicLink.AndroidParameters.Builder("com.client.traveller").build())
.setIosParameters(
DynamicLink.IosParameters.Builder("com.example.ios")
.setAppStoreId("123456789")
.setMinimumVersion("1.0.1")
.build())
.buildDynamicLink()
Log.e(javaClass.simpleName, dynamicLink.uri.toString())
val actionCodeSettings = ActionCodeSettings.newBuilder()
.setUrl(url)
.setAndroidPackageName("com.client.traveller", true, null)
.setHandleCodeInApp(true)
.setDynamicLinkDomain("travellersystems.page.link")
.build()
user?.sendEmailVerification(actionCodeSettings)
?.addOnCompleteListener{task ->
if (task.isSuccessful){
Log.e(javaClass.simpleName, "sendEmailVerification successful")
}
else{
Log.e(javaClass.simpleName, task.exception?.localizedMessage)
}
}
}
Here i'm trying get some data
private fun getDynamicLinks(){
FirebaseDynamicLinks.getInstance()
.getDynamicLink(intent)
.addOnSuccessListener(this){ pendingDynamicLinkData ->
Log.e(javaClass.simpleName, pendingDynamicLinkData?.toString() ?: intent.dataString+"")
var deepLink: Uri? = null
if (pendingDynamicLinkData != null){
deepLink = pendingDynamicLinkData.link
viewModel.setEmailVerified()
Dialog.newInstance(getString(R.string.post_email_verification)).show(this.supportFragmentManager, "Weryfikacja e-mail")
}
}
.addOnFailureListener {
Log.e(javaClass.simpleName, it.message)
}
}
Activiyt where I have getDynamicLinks in AndroidManifest:
<activity
android:name=".ui.home.HomeActivity"
android:theme="#style/AppTheme.StatusBar.Transparent">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:scheme="https"
android:host="travellersystems.page.link"
/>
</intent-filter>
</activity>
Can you say what I'm doing wrong?

Spotify Auth Library returning Type.EMPTY on login

I followed everything in the android authentication guide and the quick start guide. I did as the guide told me to generate a SHA1 and adding it to Spotify app dashboard, and I got the app_client and added it to my app as well. Both scenarios still return the same thing. I even tried implementing the Login thru Browser feature, yet it still returns type EMPTY.
Here's my Login class
class SignInActivity : AppCompatActivity(), ConnectionStateCallback, Player.NotificationCallback {
private var mPlayer : SpotifyPlayer? = null
private val CLIENT_ID = //replace this
private val REDIRECT_URI = //replace this
private val REQUEST_CODE = 1337
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
btnSignin.setOnClickListener {
val builder = AuthenticationRequest.Builder(CLIENT_ID, AuthenticationResponse.Type.TOKEN, REDIRECT_URI)
builder.setScopes(arrayOf("user-read-private", "streaming"))
val request = builder.build()
AuthenticationClient.openLoginActivity(this, REQUEST_CODE, request)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
// Check if result comes from the correct activity
if (requestCode == REQUEST_CODE) {
val response = AuthenticationClient.getResponse(resultCode, intent)
Log.i("LoginActivity", Gson().toJson(response))
when (response.type) {
// Response was successful and contains auth token
AuthenticationResponse.Type.TOKEN -> {
Log.i("LoginActivity", "is equals to TOKEN")
val playerConfig = Config(this, response.accessToken, CLIENT_ID)
Spotify.getPlayer(playerConfig, this, object : SpotifyPlayer.InitializationObserver {
override fun onInitialized(spotifyPlayer: SpotifyPlayer) {
mPlayer = spotifyPlayer
mPlayer!!.addConnectionStateCallback(this#SignInActivity)
mPlayer!!.addNotificationCallback(this#SignInActivity)
}
override fun onError(throwable: Throwable) {
Log.e("LoginActivity", "Could not initialize player: " + throwable.message)
}
})
}
// Auth flow returned an error
AuthenticationResponse.Type.ERROR -> {
Log.i("LoginActivity", "ERROR!: $response.error")
}
AuthenticationResponse.Type.EMPTY -> {
Log.i("LoginActivity", "EMPTY!")
}
}
}
}
override fun onLoggedIn() {
Log.d("LoginActivity", "User logged in")
// This is the line that plays a song.
mPlayer!!.playUri(null, "spotify:track:2TpxZ7JUBn3uw46aR7qd6V", 0, 0)
}
}
and here's my AndroidManifest file
`
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".SignInActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<data
android:host="callback"
android:scheme="backdrop.io"/>
</intent-filter>
</activity>
<activity
android:name="com.spotify.sdk.android.authentication.LoginActivity"
android:theme="#android:style/Theme.Translucent.NoTitleBar"/>
</application>
I'm trying to get a Type.TOKEN from this
Had this exact same issue myself, the problem is with this line in onActivityResult():
val response = AuthenticationClient.getResponse(resultCode, intent)
data should be passed as the second argument instead of intent.
The reason this isn't a compiler error is due to Kotlin turning getters and setters into properties, intent is a call to the Activity method getIntent().

How to trigger code in Android based on HTML

I have 2 links inside HTML code that is shown via a TextView. The first needs to open the URL in a webbrowser. The second needs to open another Activity in the App, so it must trigger some code in the App. Is this possible?
val textView = findViewById<TextView>(R.id.someTextView)
val html = "<ul>\n" +
"<li><a href=\\https://www.google.nl>Click here for google</a></li>\n" +
"<li><a href=\\scheme:open-something>Open App screen</a></li>\n" +
"</ul>\n"
textView.text = Html.fromHtml(html, Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE)
TextView:
<TextView
android:id="#+id/someTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
I've used this post as a starting point.
val textView = findViewById<TextView>(R.id.someTextView)
val html = "<ul>" +
"<li><a href='myscheme://www.google.com'>link</a></li>" +
"<li><a href='myscheme://someuniquevalue.google.com'>link jim</a></li>" +
"</ul>"
textView.setText(Html.fromHtml(html))
textView.setMovementMethod(LinkMovementMethod.getInstance())
WebViewActivity:
class WebViewActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
val url = intent.dataString!!.replace("myscheme://", "https://")
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(url)
startActivity(i)
}
}
}
Androidmanifest:
<activity android:name=".WebViewActivity" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="myscheme" />
</intent-filter>
</activity>

Categories

Resources