Skip to content

Commit

Permalink
可以使用lx直接播放本地音乐
Browse files Browse the repository at this point in the history
  • Loading branch information
likaiqiang committed Nov 16, 2023
1 parent 490ba5e commit 2ed61e9
Show file tree
Hide file tree
Showing 12 changed files with 287 additions and 69 deletions.
96 changes: 54 additions & 42 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,50 +1,62 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="cn.toside.music.mobile">
xmlns:tools="http://schemas.android.com/tools"
package="cn.toside.music.mobile">

<!-- 获取读写外置存储权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

<application
android:name=".MainApplication"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme"
tools:targetApi="n">
<activity
android:name=".MainActivity"
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>
</activity>
android:name=".MainApplication"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme"
tools:targetApi="n">
<activity
android:name=".MainActivity"
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.APP_MUSIC"/>
<data android:mimeType="audio/*"/>
<data android:mimeType="application/ogg"/>
<data android:mimeType="application/x-ogg"/>
<data android:mimeType="application/itunes"/>
<data android:scheme="content"/>
<data android:scheme="file"/>
</intent-filter>
</activity>

<!-- Define a FileProvider for API24+ -->
<!-- note this is the authority name used by other modules like rn-fetch-blob, easy to have conflicts -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<!-- you might need the tools:replace thing to workaround rn-fetch-blob or other definitions of provider -->
<!-- just make sure if you "replace" here that you include all the paths you are replacing *plus* the cache path we use -->
<meta-data tools:replace="android:resource"
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<!-- Define a FileProvider for API24+ -->
<!-- note this is the authority name used by other modules like rn-fetch-blob, easy to have conflicts -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<!-- you might need the tools:replace thing to workaround rn-fetch-blob or other definitions of provider -->
<!-- just make sure if you "replace" here that you include all the paths you are replacing *plus* the cache path we use -->
<meta-data tools:replace="android:resource"
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -1,13 +1,91 @@
package cn.toside.music.mobile;

import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.reactnativenavigation.NavigationActivity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;

import androidx.loader.content.CursorLoader;

import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;

public class MainActivity extends NavigationActivity {

class MusicPlayer{
public void sendUrl(Intent intent){
if (intent!= null && intent.getAction().equals(Intent.ACTION_VIEW)) {
// 获取intent的data,这是一个Uri对象
Uri data = intent.getData();

String realPath = getRealPathFromURI(data);

// 创建一个事件
WritableMap event = Arguments.createMap();
event.putString("path", realPath);

Log.d("Tag", event.toString());

// 发送事件到RN
MainActivity.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("onPathReceived", event);
}
}
// private String getRealPathFromURI(Uri contentUri) {
// String[] proj = { MediaStore.Audio.Media.DATA };
// Cursor cursor = managedQuery(contentUri, proj, null, null, null);
// int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
// cursor.moveToFirst();
// return cursor.getString(column_index);
// }
private String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Audio.Media.DATA };
CursorLoader loader = new CursorLoader(MainActivity.reactContext, contentUri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
}

public class MainActivity extends NavigationActivity {
private MusicPlayer musicPlayer = null;
public static ReactContext reactContext = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Intent intent = getIntent();
musicPlayer = new MusicPlayer();

final ReactInstanceManager reactInstanceManager = ((MainApplication) getApplication()).getReactNativeHost().getReactInstanceManager();
// 添加监听器
reactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext context) {
reactContext = context;
musicPlayer.sendUrl(intent);
}
});

if (reactInstanceManager.hasStartedCreatingInitialContext()) {
reactContext = reactInstanceManager.getCurrentReactContext();
// ReactContext已经创建完成,可以直接获取
musicPlayer.sendUrl(intent);
}
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
musicPlayer.sendUrl(intent);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
package cn.toside.music.mobile;

import android.app.Application;
import com.facebook.react.PackageList;
import com.reactnativenavigation.NavigationApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.reactnativenavigation.react.NavigationReactNativeHost;
import com.facebook.soloader.SoLoader;
import java.util.List;

import cn.toside.music.mobile.cache.CachePackage;
import cn.toside.music.mobile.crypto.CryptoPackage;
import cn.toside.music.mobile.gzip.GzipPackage;
import cn.toside.music.mobile.lyric.LyricPackage;
import cn.toside.music.mobile.userApi.UserApiPackage;
//import cn.toside.music.mobile.musicPlayer.MusicPlayerPackage;
import cn.toside.music.mobile.utils.UtilsPackage;

public class MainApplication extends NavigationApplication {
Expand All @@ -39,6 +37,7 @@ protected List<ReactPackage> getPackages() {
packages.add(new UtilsPackage());
packages.add(new CryptoPackage());
packages.add(new UserApiPackage());
// packages.add(new MusicPlayerPackage());
return packages;
}

Expand Down
10 changes: 9 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import { exitApp } from './utils/nativeModules/utils'
import { windowSizeTools } from './utils/windowSizeTools'
import { listenLaunchEvent } from './navigation/regLaunchedEvent'
import { tipDialog } from './utils/tools'
import {DeviceEventEmitter} from "react-native";

console.log('starting app...')
listenLaunchEvent()

void Promise.all([getFontSize(), windowSizeTools.init()]).then(async([fontSize]) => {
const startPromise = Promise.all([getFontSize(), windowSizeTools.init()]).then(async([fontSize]) => {
global.lx.fontSize = fontSize
bootLog('Font size setting loaded.')

Expand Down Expand Up @@ -75,3 +76,10 @@ void Promise.all([getFontSize(), windowSizeTools.init()]).then(async([fontSize])
exitApp()
})
})

const eventListener = DeviceEventEmitter.addListener('onPathReceived', eventParams => {
startPromise.then(()=>{
console.log('onPathReceived',eventParams);
global.cache_event.launchFilePathUpdated(eventParams.path)
})
});
2 changes: 2 additions & 0 deletions src/config/globalData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createAppEventHub } from '@/event/appEvent'
import { createListEventHub } from '@/event/listEvent'
import { createDislikeEventHub } from '@/event/dislikeEvent'
import { createStateEventHub } from '@/event/stateEvent'
import { createCachedEventHub } from '@/event/cachedEvent'
if (process.versions == null) {
// @ts-expect-error
process.versions = {
Expand Down Expand Up @@ -76,3 +77,4 @@ global.app_event = createAppEventHub()
global.list_event = createListEventHub()
global.dislike_event = createDislikeEventHub()
global.state_event = createStateEventHub()
global.cache_event = createCachedEventHub()
7 changes: 5 additions & 2 deletions src/core/music/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export const getMusicUrl = async({
if ('progress' in musicInfo) {
return getDownloadMusicUrl({ musicInfo, isRefresh, onToggleSource })
} else if (musicInfo.source == 'local') {
return getLocalMusicUrl({ musicInfo, isRefresh, onToggleSource })
return musicInfo.meta.filePath
// return getLocalMusicUrl({ musicInfo, isRefresh, onToggleSource })
} else {
return getOnlineMusicUrl({ musicInfo, isRefresh, quality, onToggleSource })
}
Expand All @@ -53,7 +54,8 @@ export const getPicPath = async({
if ('progress' in musicInfo) {
return getDownloadPicUrl({ musicInfo, isRefresh, listId, onToggleSource })
} else if (musicInfo.source == 'local') {
return getLocalPicUrl({ musicInfo, isRefresh, listId, onToggleSource })
return ''
// return getLocalPicUrl({ musicInfo, isRefresh, listId, onToggleSource })
} else {
return getOnlinePicUrl({ musicInfo, isRefresh, listId, onToggleSource })
}
Expand All @@ -71,6 +73,7 @@ export const getLyricInfo = async({
if ('progress' in musicInfo) {
return getDownloadLyricInfo({ musicInfo, isRefresh, onToggleSource })
} else if (musicInfo.source == 'local') {
// TODO
return getLocalLyricInfo({ musicInfo, isRefresh, onToggleSource })
} else {
return getOnlineLyricInfo({ musicInfo, isRefresh, onToggleSource })
Expand Down
49 changes: 49 additions & 0 deletions src/event/cachedEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Event from './Event'

export class CachedEvent extends Event {
cache: Map<string, Array<any>>

constructor() {
super()
this.cache = new Map()
}

on(eventName: string, listener: (...args: any[]) => any) {
super.on(eventName, listener)

// 检查缓存中是否有提前 emit 的事件
let cachedEvents = this.cache.get(eventName)
if (cachedEvents) {
for (let args of cachedEvents) {
listener(...args)
}
this.cache.delete(eventName)
}
}

emit(eventName: string, ...args: any[]) {
super.emit(eventName, ...args)

// 如果没有监听器,将事件保存到缓存中
if (!this.listeners.has(eventName)) {
let cachedEvents = this.cache.get(eventName)
if (!cachedEvents) this.cache.set(eventName, cachedEvents = [])
cachedEvents.push(args)
}
}
launchFilePathUpdated(path:string){
this.emit('launchFilePathUpdated', path)
}

}
// type EventMethods = Omit<EventType, keyof Event>
//
// declare class EventType extends CachedEvent {
// on<K extends keyof EventMethods>(event: K, listener: EventMethods[K]): any
// off<K extends keyof EventMethods>(event: K, listener: EventMethods[K]): any
// }

export const createCachedEventHub = (): CachedEvent => {
return new CachedEvent()
}

Loading

0 comments on commit 2ed61e9

Please sign in to comment.