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.
Related
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?
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 ?
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?
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().
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>