feat: sync catalog, server, and MusicFree updates
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="fun.upup.musicfree">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/AppTheme"
|
||||
android:supportsRtl="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:extractNativeLibs="true"
|
||||
>
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:theme="@style/Theme.App.SplashScreen"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<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="musicfree" android:host="app"/>
|
||||
<data android:scheme="musicfree" android:host="install"/>
|
||||
</intent-filter>
|
||||
<!-- 处理音频文件 -->
|
||||
<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="file" />
|
||||
<data android:mimeType="audio/*" />
|
||||
</intent-filter>
|
||||
<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="content" />
|
||||
<data android:mimeType="audio/*" />
|
||||
</intent-filter>
|
||||
<!-- 处理特定音频格式 -->
|
||||
<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="file" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.mp3" />
|
||||
<data android:pathPattern=".*\\.MP3" />
|
||||
</intent-filter>
|
||||
<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="file" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.flac" />
|
||||
<data android:pathPattern=".*\\.FLAC" />
|
||||
</intent-filter>
|
||||
<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="file" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.m4a" />
|
||||
<data android:pathPattern=".*\\.M4A" />
|
||||
</intent-filter>
|
||||
<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="file" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.wav" />
|
||||
<data android:pathPattern=".*\\.WAV" />
|
||||
</intent-filter>
|
||||
<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="content" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.mp3" />
|
||||
<data android:pathPattern=".*\\.MP3" />
|
||||
</intent-filter>
|
||||
<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="content" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.flac" />
|
||||
<data android:pathPattern=".*\\.FLAC" />
|
||||
</intent-filter>
|
||||
<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="content" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.m4a" />
|
||||
<data android:pathPattern=".*\\.M4A" />
|
||||
</intent-filter>
|
||||
<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="content" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.wav" />
|
||||
<data android:pathPattern=".*\\.WAV" />
|
||||
</intent-filter>
|
||||
<!-- 处理JavaScript文件 -->
|
||||
<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="file" />
|
||||
<data android:mimeType="text/javascript" />
|
||||
</intent-filter>
|
||||
<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="content" />
|
||||
<data android:mimeType="text/javascript" />
|
||||
</intent-filter>
|
||||
<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="file" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.js" />
|
||||
<data android:pathPattern=".*\\.JS" />
|
||||
</intent-filter>
|
||||
<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="content" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.js" />
|
||||
<data android:pathPattern=".*\\.JS" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -11,7 +11,12 @@ import android.provider.Settings
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowManager
|
||||
import androidx.core.app.NotificationChannelCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import `fun`.upup.musicfree.MainActivity
|
||||
import `fun`.upup.musicfree.R
|
||||
import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.Promise
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
@@ -23,6 +28,8 @@ import kotlin.system.exitProcess
|
||||
class UtilsModule(context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
|
||||
|
||||
private val reactContext: ReactApplicationContext = context;
|
||||
private val playbackDiagnosticChannelId = "musicfree_playback_diag"
|
||||
private val playbackDiagnosticNotificationId = 42042
|
||||
|
||||
override fun getName() = "NativeUtils"
|
||||
|
||||
@@ -96,6 +103,61 @@ class UtilsModule(context: ReactApplicationContext) : ReactContextBaseJavaModule
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun showPlaybackDiagnosticNotification(title: String, message: String, promise: Promise) {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
val hasPermission = ContextCompat.checkSelfPermission(
|
||||
reactContext,
|
||||
Manifest.permission.POST_NOTIFICATIONS,
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
if (!hasPermission) {
|
||||
promise.resolve(null)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val manager = NotificationManagerCompat.from(reactContext)
|
||||
val channel = NotificationChannelCompat.Builder(
|
||||
playbackDiagnosticChannelId,
|
||||
NotificationManagerCompat.IMPORTANCE_HIGH,
|
||||
)
|
||||
.setName("Playback Diagnostics")
|
||||
.setDescription("Playback error and stall diagnostics")
|
||||
.build()
|
||||
manager.createNotificationChannel(channel)
|
||||
|
||||
val intent = Intent(reactContext, MainActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
}
|
||||
val pendingIntentFlags =
|
||||
android.app.PendingIntent.FLAG_UPDATE_CURRENT or
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) android.app.PendingIntent.FLAG_IMMUTABLE else 0
|
||||
val pendingIntent = android.app.PendingIntent.getActivity(
|
||||
reactContext,
|
||||
0,
|
||||
intent,
|
||||
pendingIntentFlags,
|
||||
)
|
||||
|
||||
val notification = NotificationCompat.Builder(reactContext, playbackDiagnosticChannelId)
|
||||
.setSmallIcon(R.mipmap.ic_launcher)
|
||||
.setContentTitle(title)
|
||||
.setContentText(message)
|
||||
.setStyle(NotificationCompat.BigTextStyle().bigText(message))
|
||||
.setContentIntent(pendingIntent)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.build()
|
||||
|
||||
manager.notify(playbackDiagnosticNotificationId, notification)
|
||||
promise.resolve(null)
|
||||
} catch (e: Exception) {
|
||||
promise.reject("show_playback_diagnostic_notification_failed", e)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
fun getWindowDimensions(): WritableMap {
|
||||
val windowManager = reactApplicationContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
|
||||
Reference in New Issue
Block a user