From 916004b699ef72f20e5c6a368f6236742116644a Mon Sep 17 00:00:00 2001 From: EricLu Date: Tue, 23 Sep 2025 09:39:45 +0800 Subject: [PATCH 1/4] dev: use standalone kotlin-parcelize Gradle plugin --- line-sdk/build.gradle | 8 ++++++-- .../com/linecorp/linesdk/openchat/OpenChatRoomInfo.kt | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/line-sdk/build.gradle b/line-sdk/build.gradle index 5a83d9d..5dcc32b 100644 --- a/line-sdk/build.gradle +++ b/line-sdk/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-kapt' apply plugin: 'maven-publish' @@ -26,6 +26,10 @@ android { enabled = true } + viewBinding { + enabled = true + } + libraryVariants.all { variant -> variant.outputs.all { output -> def fileName = "line-sdk-${defaultConfig.versionName}" @@ -60,7 +64,7 @@ configurations { dependencies { javadocs "androidx.annotation:annotation:${ver.androidx.annotation}" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${ver.kotlin}" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${ver.kotlin}" implementation "androidx.annotation:annotation:${ver.androidx.annotation}" implementation "androidx.appcompat:appcompat:${ver.androidx.appcompat}" diff --git a/line-sdk/src/main/java/com/linecorp/linesdk/openchat/OpenChatRoomInfo.kt b/line-sdk/src/main/java/com/linecorp/linesdk/openchat/OpenChatRoomInfo.kt index d636265..004a819 100644 --- a/line-sdk/src/main/java/com/linecorp/linesdk/openchat/OpenChatRoomInfo.kt +++ b/line-sdk/src/main/java/com/linecorp/linesdk/openchat/OpenChatRoomInfo.kt @@ -1,7 +1,7 @@ package com.linecorp.linesdk.openchat import android.os.Parcelable -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize @Parcelize data class OpenChatRoomInfo( From db59b8d62bcdccf0b27c542173177e534dfaef4e Mon Sep 17 00:00:00 2001 From: EricLu Date: Tue, 23 Sep 2025 09:52:40 +0800 Subject: [PATCH 2/4] dev: replace kotlinx.android.synthetic with viewBinding --- .../sample/ui/theme/LineSdkAndroidTheme.kt | 2 ++ .../openchat/ui/CreateOpenChatActivity.kt | 11 +++++--- .../openchat/ui/OpenChatInfoFragment.kt | 26 +++++++------------ .../openchat/ui/ProfileInfoFragment.kt | 9 +++---- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/linecorp/linesdk/sample/ui/theme/LineSdkAndroidTheme.kt b/app/src/main/java/com/linecorp/linesdk/sample/ui/theme/LineSdkAndroidTheme.kt index b51e5ee..d281c88 100644 --- a/app/src/main/java/com/linecorp/linesdk/sample/ui/theme/LineSdkAndroidTheme.kt +++ b/app/src/main/java/com/linecorp/linesdk/sample/ui/theme/LineSdkAndroidTheme.kt @@ -1,5 +1,6 @@ package com.linecorp.linesdk.sample.ui.theme +import android.annotation.SuppressLint import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme @@ -71,6 +72,7 @@ private val DarkColors = darkColorScheme( ) @Composable +@SuppressLint("NewApi") fun LineSdkAndroidTheme( useDarkTheme: Boolean = isSystemInDarkTheme(), dynamicColor: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S, diff --git a/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/CreateOpenChatActivity.kt b/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/CreateOpenChatActivity.kt index e4a7310..45a8527 100644 --- a/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/CreateOpenChatActivity.kt +++ b/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/CreateOpenChatActivity.kt @@ -19,12 +19,14 @@ import com.linecorp.linesdk.R import com.linecorp.linesdk.api.LineApiClient import com.linecorp.linesdk.api.LineApiClientBuilder import com.linecorp.linesdk.auth.internal.LineAppVersion +import com.linecorp.linesdk.databinding.ActivityCreateOpenChatBinding import com.linecorp.linesdk.openchat.OpenChatRoomInfo -import kotlinx.android.synthetic.main.activity_create_open_chat.progressBar class CreateOpenChatActivity : AppCompatActivity() { private enum class CreateOpenChatStep { ChatroomInfo, UserProfile } + private lateinit var binding: ActivityCreateOpenChatBinding + private val lineApiClient: LineApiClient by lazy { val channelId = intent.getStringExtra(ARG_CHANNEL_ID).orEmpty() LineApiClientBuilder(this, channelId) @@ -37,7 +39,8 @@ class CreateOpenChatActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_create_open_chat) + binding = ActivityCreateOpenChatBinding.inflate(layoutInflater) + setContentView(binding.root) initViewModel() @@ -49,6 +52,8 @@ class CreateOpenChatActivity : AppCompatActivity() { fun goToNextScreen() = addFragment(CreateOpenChatStep.UserProfile) + fun getToolbar() = binding.toolbar + private fun initViewModel() { val sharedPreferences = getSharedPreferences("openchat", Context.MODE_PRIVATE) viewModel = ViewModelProvider( @@ -80,7 +85,7 @@ class CreateOpenChatActivity : AppCompatActivity() { }) viewModel.isCreatingChatRoom.observe(this, Observer { isCreatingChatRoom -> - progressBar.visibility = if (isCreatingChatRoom) VISIBLE else GONE + binding.progressBar.visibility = if (isCreatingChatRoom) VISIBLE else GONE }) viewModel.shouldShowAgreementWarning.observe(this, Observer { shouldShowWarning -> diff --git a/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/OpenChatInfoFragment.kt b/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/OpenChatInfoFragment.kt index 83475ac..4025141 100644 --- a/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/OpenChatInfoFragment.kt +++ b/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/OpenChatInfoFragment.kt @@ -12,14 +12,6 @@ import androidx.lifecycle.ViewModelProvider import com.linecorp.linesdk.R import com.linecorp.linesdk.databinding.OpenChatInfoFragmentBinding import com.linecorp.linesdk.openchat.addAfterTextChangedAction -import kotlinx.android.synthetic.main.activity_create_open_chat.toolbar -import kotlinx.android.synthetic.main.open_chat_info_fragment.categoryLabelTextView -import kotlinx.android.synthetic.main.open_chat_info_fragment.descriptionEditText -import kotlinx.android.synthetic.main.open_chat_info_fragment.descriptionMaxTextView -import kotlinx.android.synthetic.main.open_chat_info_fragment.nameEditText -import kotlinx.android.synthetic.main.open_chat_info_fragment.nameMaxTextView -import kotlinx.android.synthetic.main.open_chat_info_fragment.searchIncludedCheckBox -import kotlinx.android.synthetic.main.open_chat_info_fragment.searchIncludedContainer class OpenChatInfoFragment : Fragment() { @@ -55,18 +47,18 @@ class OpenChatInfoFragment : Fragment() { binding.viewModel = viewModel viewModel.chatroomName.observe(this, Observer { name -> - nameMaxTextView.text = + binding.nameMaxTextView.text = generateTextLengthLimitString(name, R.integer.max_chatroom_name_length) }) viewModel.description.observe(this, Observer { name -> - descriptionMaxTextView.text = + binding.descriptionMaxTextView.text = generateTextLengthLimitString(name, R.integer.max_chatroom_description_length) }) viewModel.category.observe(this, Observer { category -> category?.resourceId?.let { resourceId -> - categoryLabelTextView.text = resources.getString(resourceId) + binding.categoryLabelTextView.text = resources.getString(resourceId) } }) } @@ -80,7 +72,7 @@ class OpenChatInfoFragment : Fragment() { } private fun setupToolbar() { - val toolbar = requireActivity().toolbar.apply { + val toolbar = (requireActivity() as CreateOpenChatActivity).getToolbar().apply { title = getString(R.string.openchat_create_room_title) menu.clear() inflateMenu(R.menu.menu_openchat_info) @@ -107,15 +99,15 @@ class OpenChatInfoFragment : Fragment() { } private fun setupSearchOption() { - searchIncludedCheckBox.setOnCheckedChangeListener { _, isChecked -> + binding.searchIncludedCheckBox.setOnCheckedChangeListener { _, isChecked -> viewModel.isSearchIncluded.value = isChecked } - searchIncludedContainer.setOnClickListener { searchIncludedCheckBox.toggle() } + binding.searchIncludedContainer.setOnClickListener { binding.searchIncludedCheckBox.toggle() } } private fun setupCategoryLabel() { - categoryLabelTextView.setOnClickListener { showCategorySelectionDialog() } + binding.categoryLabelTextView.setOnClickListener { showCategorySelectionDialog() } } private fun showCategorySelectionDialog() = @@ -127,10 +119,10 @@ class OpenChatInfoFragment : Fragment() { .show() private fun setupDescription() = - descriptionEditText.addAfterTextChangedAction(viewModel.description::setValue) + binding.descriptionEditText.addAfterTextChangedAction(viewModel.description::setValue) private fun setupName() = - nameEditText.addAfterTextChangedAction(viewModel.chatroomName::setValue) + binding.nameEditText.addAfterTextChangedAction(viewModel.chatroomName::setValue) private fun getResourceInt(@IntegerRes resId: Int): Int = requireActivity().resources.getInteger(resId) diff --git a/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/ProfileInfoFragment.kt b/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/ProfileInfoFragment.kt index 27a3ad8..fae3c77 100644 --- a/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/ProfileInfoFragment.kt +++ b/line-sdk/src/main/java/com/linecorp/linesdk/openchat/ui/ProfileInfoFragment.kt @@ -12,9 +12,6 @@ import androidx.lifecycle.ViewModelProvider import com.linecorp.linesdk.R import com.linecorp.linesdk.databinding.ProfileInfoFragmentBinding import com.linecorp.linesdk.openchat.addAfterTextChangedAction -import kotlinx.android.synthetic.main.activity_create_open_chat.toolbar -import kotlinx.android.synthetic.main.profile_info_fragment.displayNameEditText -import kotlinx.android.synthetic.main.profile_info_fragment.displayNameGuide class ProfileInfoFragment : Fragment() { @@ -54,16 +51,16 @@ class ProfileInfoFragment : Fragment() { } private fun setupProfileNameGuide() { - displayNameGuide.text = resources.getString(R.string.openchat_create_profile_input_guide, viewModel.chatroomName.value) + binding.displayNameGuide.text = resources.getString(R.string.openchat_create_profile_input_guide, viewModel.chatroomName.value) } private fun setupProfileName() = - displayNameEditText.addAfterTextChangedAction { name -> + binding.displayNameEditText.addAfterTextChangedAction { name -> viewModel.profileName.value = name } private fun setupToolbar() { - val toolbar = requireActivity().toolbar.apply { + val toolbar = (requireActivity() as CreateOpenChatActivity).getToolbar().apply { title = getString(R.string.openchat_create_profile_title) menu.clear() inflateMenu(R.menu.menu_profile_info) From 971b2df74b968fda856e6deb6ba3df307d0e5cf7 Mon Sep 17 00:00:00 2001 From: EricLu Date: Tue, 23 Sep 2025 14:21:08 +0800 Subject: [PATCH 3/4] docs: add known issue for Motorola devices login problem - Document login issue caused by Moto Secure app's Phishing detection feature - Provide step-by-step workaround instructions for developers to guide their users --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index 22ff8b2..b9e3923 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,25 @@ To resolve this issue, you can either clear the package signatures field or conf For more information, refer to the [LINE SDK for Android guide](https://developers.line.biz/en/docs/android-sdk/) on the [LINE Developers site](https://developers.line.biz). +# Known Issues + +## Motorola Android Devices Login Issue + +We've identified an issue affecting LINE Login functionality specifically on Motorola Android devices. The problem is caused by the Phishing detection feature in the Moto Secure app that comes pre-installed on these devices. + +### Solution for Developers + +If your users report login failures on Motorola devices, please guide them through these steps: + +1. Open the Moto Secure app on their Motorola device +1. Navigate to "Phishing detection" +1. Temporarily disable this feature +1. Attempt to log in to your app using LINE Login +1. Once login is successful, they can safely re-enable the "Phishing detection" feature + +Consider displaying them when detecting login failures on Motorola devices to improve user experience. + +We are investigating the root cause and its solution. # Try the starter app To have a quick look at the features of the LINE SDK, try our starter app by following the steps below: From 16415e962aec48272b7c6f7657e144bf1d8b05c8 Mon Sep 17 00:00:00 2001 From: EricLu Date: Wed, 24 Sep 2025 17:52:11 +0800 Subject: [PATCH 4/4] dev: bump LINE SDK version to 5.12.0 --- app/build.gradle.kts | 2 +- line-sdk/build.gradle | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index dd6cae3..fab94e3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -51,7 +51,7 @@ android { } dependencies { - implementation("com.linecorp.linesdk:linesdk:5.11.1") + implementation("com.linecorp.linesdk:linesdk:5.12.0") implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.5.1") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1") diff --git a/line-sdk/build.gradle b/line-sdk/build.gradle index 5dcc32b..3c0758d 100644 --- a/line-sdk/build.gradle +++ b/line-sdk/build.gradle @@ -7,15 +7,14 @@ apply plugin: 'maven-publish' apply plugin: 'signing' group = "com.linecorp.linesdk" -version = "5.11.1" +version = "5.12.0" android { compileSdk 33 defaultConfig { minSdkVersion 24 - targetSdkVersion 33 - versionCode 5_11_01 + versionCode 5_12_00 versionName version consumerProguardFiles 'consumer-proguard-rules.pro'