diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index b6e2f8e1..be6fcbe7 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v3 - - name: set up JDK 11 + - name: set up JDK uses: actions/setup-java@v3 with: distribution: 'oracle' diff --git a/app/build.gradle b/app/build.gradle index f6f252e0..d8a056e4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -92,9 +92,15 @@ android { // proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } - composeOptions { - kotlinCompilerExtensionVersion '1.4.3' + kotlinCompilerExtensionVersion '1.4.6' + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = '17' } } @@ -106,11 +112,9 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' - implementation 'androidx.core:core-ktx:1.9.0' + implementation 'androidx.core:core-ktx:1.10.0' implementation 'androidx.browser:browser:1.5.0' implementation 'androidx.preference:preference-ktx:1.2.0' - implementation 'androidx.core:core-splashscreen:1.0.0' - //implementation 'androidx.datastore:datastore-preferences:1.0.0' //Web Service Setup implementation 'com.google.code.gson:gson:2.10.1' @@ -136,7 +140,7 @@ dependencies { implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0' //Design Setup - implementation 'com.google.android.material:material:1.9.0-beta01' + implementation 'com.google.android.material:material:1.8.0' implementation 'com.airbnb.android:lottie:6.0.0' implementation 'com.github.akshaaatt:Onboarding:1.0.5' implementation 'com.github.akshaaatt:Share-Android:1.0.0' @@ -159,10 +163,10 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.1' implementation 'androidx.hilt:hilt-navigation-compose:1.0.0' implementation 'com.airbnb.android:lottie-compose:6.0.0' - implementation 'androidx.activity:activity-compose:1.7.0' + implementation 'androidx.activity:activity-compose:1.7.1' // Compose Navigation - implementation 'androidx.navigation:navigation-compose:2.6.0-alpha09' // Stable one + implementation 'androidx.navigation:navigation-compose:2.6.0-beta01' // Stable one implementation "com.google.accompanist:accompanist-navigation-animation:$accompanist_version" // Experimental but has animations //Spotify diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5c3289d1..9e74e512 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,9 +13,12 @@ + + + + + android:theme="@style/AppThemeNoActionBar" > diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/dashboard/DashboardActivity.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/dashboard/DashboardActivity.kt index b165387f..cc90e926 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/dashboard/DashboardActivity.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/dashboard/DashboardActivity.kt @@ -13,7 +13,6 @@ import androidx.compose.material.Scaffold import androidx.compose.material.rememberBackdropScaffoldState import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.* -import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.navigation.compose.rememberNavController import com.google.accompanist.pager.ExperimentalPagerApi import dagger.hilt.android.AndroidEntryPoint @@ -34,7 +33,6 @@ class DashboardActivity : ComponentActivity() { @SuppressLint("UnusedMaterialScaffoldPaddingParameter") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - installSplashScreen() setContent { ListenBrainzTheme { // TODO: Since this view-model will remain throughout the lifecycle of the app, diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/listens/AllUsersListens.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/listens/AllUsersListens.kt index abba3937..30b6eefa 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/listens/AllUsersListens.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/listens/AllUsersListens.kt @@ -188,6 +188,7 @@ private fun ListensList( scope.launch { val videoId = viewModel .searchYoutubeMusicVideoId( + context = context, trackName = listen.track_metadata.track_name, artist = listen.track_metadata.artist_name, apiKey = youtubeApiKey @@ -200,8 +201,10 @@ private fun ListensList( val intent = Intent(Intent.ACTION_VIEW) intent.data = trackUri intent.setPackage(Constants.YOUTUBE_MUSIC_PACKAGE_NAME) + val activities = context.packageManager.queryIntentActivities(intent, 0) + when { - intent.resolveActivity(context.packageManager) != null -> { + activities.isNotEmpty() -> { context.startActivity(intent) } diff --git a/app/src/main/java/org/listenbrainz/android/util/NotificationHelper.kt b/app/src/main/java/org/listenbrainz/android/util/NotificationHelper.kt index 88033870..93480acf 100644 --- a/app/src/main/java/org/listenbrainz/android/util/NotificationHelper.kt +++ b/app/src/main/java/org/listenbrainz/android/util/NotificationHelper.kt @@ -44,7 +44,12 @@ class NotificationHelper(base: Context?,val icon: Bitmap) : ContextWrapper(base) .setPriority(NotificationCompat.PRIORITY_MAX) .setTimeoutAfter(1800000) .setAutoCancel(true) - .setContentIntent(PendingIntent.getActivity(baseContext, 0, Intent(baseContext, intentActivity), 0)) + .setContentIntent(PendingIntent.getActivity( + baseContext, + 0, + Intent(baseContext, intentActivity), + PendingIntent.FLAG_IMMUTABLE + )) companion object { const val channelID = "channelId" diff --git a/app/src/main/java/org/listenbrainz/android/util/Utils.kt b/app/src/main/java/org/listenbrainz/android/util/Utils.kt index 2f0b8642..691b9559 100644 --- a/app/src/main/java/org/listenbrainz/android/util/Utils.kt +++ b/app/src/main/java/org/listenbrainz/android/util/Utils.kt @@ -4,6 +4,7 @@ import android.content.ContentValues import android.content.Context import android.content.ContextWrapper import android.content.Intent +import android.content.pm.PackageManager import android.graphics.Bitmap import android.media.MediaScannerConnection import android.net.Uri @@ -16,6 +17,8 @@ import kotlinx.coroutines.Dispatchers import okhttp3.* import org.listenbrainz.android.util.Log.e import java.io.* +import java.security.MessageDigest +import java.security.NoSuchAlgorithmException import java.util.* /** @@ -41,6 +44,22 @@ object Utils { return intent } + fun getSHA1(context: Context, packageName: String): String? { + try { + val signatures = context.packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures + for (signature in signatures) { + val md = MessageDigest.getInstance("SHA-1") + md.update(signature.toByteArray()) + return md.digest().joinToString("") { "%02X".format(it) } + } + } catch (e: PackageManager.NameNotFoundException) { + e.printStackTrace() + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } + return null + } + fun stringFromAsset(context: Context, asset: String?): String { return try { val input = context.resources.assets.open(asset!!) diff --git a/app/src/main/java/org/listenbrainz/android/viewmodel/ListensViewModel.kt b/app/src/main/java/org/listenbrainz/android/viewmodel/ListensViewModel.kt index 483c4470..799741c3 100644 --- a/app/src/main/java/org/listenbrainz/android/viewmodel/ListensViewModel.kt +++ b/app/src/main/java/org/listenbrainz/android/viewmodel/ListensViewModel.kt @@ -1,6 +1,7 @@ package org.listenbrainz.android.viewmodel import android.app.Application +import android.content.Context import android.graphics.Bitmap import android.util.Log import androidx.compose.runtime.getValue @@ -23,6 +24,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import okhttp3.OkHttpClient import org.listenbrainz.android.BuildConfig import org.listenbrainz.android.model.Listen import org.listenbrainz.android.repository.AppPreferences @@ -36,6 +38,7 @@ import org.listenbrainz.android.util.Resource.Status.FAILED import org.listenbrainz.android.util.Resource.Status.LOADING import org.listenbrainz.android.util.Resource.Status.SUCCESS import org.listenbrainz.android.util.Utils.getCoverArtUrl +import org.listenbrainz.android.util.Utils.getSHA1 import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Inject @@ -108,10 +111,24 @@ class ListensViewModel @Inject constructor( } } - suspend fun searchYoutubeMusicVideoId(trackName: String, artist: String, apiKey: String): String? { + suspend fun searchYoutubeMusicVideoId(context: Context, trackName: String, artist: String, apiKey: String): String? { + val packageName = context.packageName + val sha1 = getSHA1(context, packageName) + + val okHttpClient = OkHttpClient.Builder() + .addInterceptor { chain -> + val request = chain.request().newBuilder() + .addHeader("X-Android-Package", packageName) + .addHeader("X-Android-Cert", sha1 ?: "") + .build() + chain.proceed(request) + } + .build() + val retrofit = Retrofit.Builder() .baseUrl("https://www.googleapis.com/") .addConverterFactory(GsonConverterFactory.create()) + .client(okHttpClient) .build() val service = retrofit.create(YouTubeApiService::class.java) diff --git a/app/src/main/res/values-h720dp/dimensions.xml b/app/src/main/res/values-h720dp/dimensions.xml deleted file mode 100644 index 5fb5fe38..00000000 --- a/app/src/main/res/values-h720dp/dimensions.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index 166db542..166a6eb1 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -15,16 +15,6 @@ false - - diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index b9b132dc..3c89330e 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -13,16 +13,6 @@ true - - diff --git a/build.gradle b/build.gradle index 5522df7d..899f943c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,20 +1,20 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext { - kotlin_version = '1.8.10' + kotlin_version = '1.8.20' navigationVersion = '2.5.3' hilt_version = '2.45' - compose_version = '1.4.1' + compose_version = '1.4.2' room_version = '2.5.1' accompanist_version = '0.30.0' - exoplayer_version = '2.18.5' + exoplayer_version = '2.18.6' } repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.android.tools.build:gradle:8.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" } diff --git a/gradle.properties b/gradle.properties index 7299f326..1bff1a66 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,7 @@ org.gradle.jvmargs=-Xmx4096m android.useAndroidX=true android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false #org.gradle.configuration-cache=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 315dde76..5568b3b9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Fri Jan 13 19:40:00 IST 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/sharedTest/build.gradle b/sharedTest/build.gradle index 87048fd3..e1d11b1a 100644 --- a/sharedTest/build.gradle +++ b/sharedTest/build.gradle @@ -19,6 +19,15 @@ android { minifyEnabled false } } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = '17' + } } dependencies {