反应本机RingtoneManager

时间:2019-04-19 23:11:11

标签: react-native ringtonemanager

我正在使用https://github.com/millerbennett/react-native-ringtone-manager

但是不幸的是,RingtoneManager.getRingtones(RingtoneManager.TYPE_ALL)始终返回“未定义”。

我没有错误,有人知道这个问题吗?

我正在使用仿真器,但是我可以看到参数中存在铃声。

编辑

我又回到了这个问题上。

我不明白为什么它不起作用。

我阅读了https://github.com/millerbennett/react-native-ringtone-manager并与经理的代码进行了比较,但没有发现任何问题。

实际上,对象RingtoneManager本身被标记为未定义

编辑

这是我的代码:

import React from 'react';
import { Text, View} from 'react-native';
import RingtoneManager from 'react-native-ringtone-manager';


export default class FormRingtones extends React.Component {

static navigationOptions = {
  title: 'Rings',
};
constructor(props) {
super(props);

}
rings;

componentDidMount() {
this.getRings();
}

getRings() {
console.log("1 : " + RingtoneManager);
 this.rings =  RingtoneManager.getRingtones(RingtoneManager.TYPE_ALL);
 if(this.rings != null) {this.rings = this.rings.map((item,index) =>{<Text>{item.title}</Text>})};
   console.log("2 " + this.rings.length);

}

render() {   
return (
  <View>
    <View >
      {this.rings}
    </View>
  </View>
)
};
}

我刚刚按照评论中的说明安装了最新版本,现在该应用程序显示了一个不错的“未知”错误,调试工具中没有其他内容……

清除缓存并重新启动所有工具,救了我。

但是现在我有[object Object]用于RingtoneManager,并且 undefined 用于铃声...

谢谢您的帮助。

编辑

对不起,我现在还没有时间发布解决方案。

问题是getRingtones()在react-native-ringtone-manager中只是空的。。。。。。。。。。。。。。。

好吧,我做了什么:

node_modules \ react-native-ringtone-manager \ android \ src \ main \ java \ com \ reactlibrary 中,在 RNRingtoneManagerModule.java 中:

@ReactMethod
public void getRingtones(Callback successCallback) {
    getRingsByType(RingtoneManager.TYPE_ALL, successCallback);
}

@ReactMethod
public void getRingsByType(int ringtoneType, Callback successCallback)          {
    RingtoneManager manager = new RingtoneManager(this.reactContext);
    manager.setType(ringtoneType);
    Cursor cursor = manager.getCursor();
    WritableMap data = Arguments.createMap();

    while (cursor.moveToNext()) {
        String notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
        Uri notificationUri =Uri.parse(cursor.getString(RingtoneManager.URI_COLUMN_INDEX) + "/" + cursor.getString(RingtoneManager.ID_COLUMN_INDEX));
        data.putString(notificationTitle, notificationUri);

    }
    successCallback.invoke(data);
}

现在,一切正常,我可以按类型列出铃声,播放声音等...

这是我一生中第一次安装在:)

之后必须写的东西。

1 个答案:

答案 0 :(得分:1)

此外,我发布了我的整个代码。还没有完全完成,因为我解决了RingToneManager的主要问题,所以我在应用程序的其他部分上工作。但这对于遇到铃声问题的人来说是一个好的开始:

RNRingtoneManagerModule

package com.reactlibrary;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.media.RingtoneManager;
import android.net.Uri;
import android.provider.MediaStore;
import android.database.Cursor;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.Arguments;

import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

import java.net.URISyntaxException;

public class RNRingtoneManagerModule extends ReactContextBaseJavaModule {

private final ReactApplicationContext reactContext;
private static final String TYPE_ALARM_KEY = "TYPE_ALARM";
private static final String TYPE_ALL_KEY = "TYPE_ALL";
private static final String TYPE_NOTIFICATION_KEY = "TYPE_NOTIFICATION";
private static final String TYPE_RINGTONE_KEY = "TYPE_RINGTONE";

final static class SettingsKeys {
    public static final String URI = "uri";
    public static final String TITLE = "title";
    public static final String ARTIST = "artist";
    public static final String SIZE = "size";
    public static final String MIME_TYPE = "mimeType";
    public static final String DURATION = "duration";
    public static final String RINGTONE_TYPE = "ringtoneType";
}

public RNRingtoneManagerModule(ReactApplicationContext reactContext) {
    super(reactContext);
    this.reactContext = reactContext;
}

@Override
public String getName() {
    return "RingtoneManager";
}

@ReactMethod
public void getRingtones(Callback successCallback) {
    getRingsByType(RingtoneManager.TYPE_ALL, successCallback);
}

@ReactMethod
public void getRingsByType(int ringtoneType, Callback successCallback) {
    RingtoneManager manager = new RingtoneManager(this.reactContext);
    manager.setType(ringtoneType);
    Cursor cursor = manager.getCursor();

    WritableArray result = Arguments.createArray();
    int key= 0;
    while (cursor.moveToNext()) { 
        WritableMap data = Arguments.createMap();
        String notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
        Uri notificationUri = Uri.parse(cursor.getString(RingtoneManager.URI_COLUMN_INDEX) + "/"
                + cursor.getString(RingtoneManager.ID_COLUMN_INDEX));
        String notification = getPathFromUri(this.reactContext, notificationUri);
        data.putInt("key", key);
        data.putString("title", notificationTitle);
        data.putString("uri", notification);
        result.pushMap(data);
        key=key+1;
    }
    successCallback.invoke(result);
}

@SuppressLint("NewApi")
public String getPathFromUri(Context context, Uri uri) {
    final boolean needToCheckUri = Build.VERSION.SDK_INT >= 19;
    String selection = null;
    String[] selectionArgs = null;
    // Uri is different in versions after KITKAT (Android 4.4), we need to
    // deal with different Uris.
    if (needToCheckUri && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            return Environment.getExternalStorageDirectory() + "/" + split[1];
        } else if (isDownloadsDocument(uri)) {
            final String id = DocumentsContract.getDocumentId(uri);
            uri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
        } else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            if ("image".equals(type)) {
                uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }
            selection = "_id=?";
            selectionArgs = new String[] { split[1] };
        }
    }
    if ("content".equalsIgnoreCase(uri.getScheme())) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = null;
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            if (cursor.moveToFirst()) {
                return cursor.getString(column_index);
            }
        } catch (Exception e) {
        }
    } else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }
    return null;
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is ExternalStorageProvider.
 */
public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 */
public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 */
public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

@ReactMethod
public void createRingtone(ReadableMap settings) {
    String uriStr = settings.getString(SettingsKeys.URI);
    File ringtone = new File(uriStr);
    ContentValues values = new ContentValues();
    values.put(MediaStore.MediaColumns.DATA, ringtone.getAbsolutePath());
    values.put(MediaStore.MediaColumns.TITLE, settings.getString(SettingsKeys.TITLE));
    values.put(MediaStore.MediaColumns.SIZE, settings.getInt(SettingsKeys.SIZE));
    values.put(MediaStore.MediaColumns.MIME_TYPE, settings.getString(SettingsKeys.MIME_TYPE));
    values.put(MediaStore.Audio.Media.ARTIST, settings.getString(SettingsKeys.ARTIST));
    values.put(MediaStore.Audio.Media.DURATION, settings.getInt(SettingsKeys.DURATION));
    int ringtoneType = settings.getInt(SettingsKeys.RINGTONE_TYPE);
    values.put(MediaStore.Audio.Media.IS_RINGTONE, isRingtoneType(ringtoneType, RingtoneManager.TYPE_RINGTONE));
    values.put(MediaStore.Audio.Media.IS_NOTIFICATION,
            isRingtoneType(ringtoneType, RingtoneManager.TYPE_NOTIFICATION));
    values.put(MediaStore.Audio.Media.IS_ALARM, isRingtoneType(ringtoneType, RingtoneManager.TYPE_ALARM));
    values.put(MediaStore.Audio.Media.IS_MUSIC, false);
    if (ringtone.exists() && getCurrentActivity() != null) {
        ContentResolver contentResolver = getCurrentActivity().getContentResolver();
        Uri uri = MediaStore.Audio.Media.getContentUriForPath(ringtone.getAbsolutePath());
        contentResolver.insert(uri, values);
    }
}

@ReactMethod
public void setRingtone(String uri) {

}

@ReactMethod
public void pickRingtone() {

}

@Override
public Map<String, Object> getConstants() {
    final Map<String, Object> constants = new HashMap<>();
    constants.put(TYPE_ALARM_KEY, RingtoneManager.TYPE_ALARM);
    constants.put(TYPE_ALL_KEY, RingtoneManager.TYPE_ALL);
    constants.put(TYPE_NOTIFICATION_KEY, RingtoneManager.TYPE_NOTIFICATION);
    constants.put(TYPE_RINGTONE_KEY, RingtoneManager.TYPE_RINGTONE);
    return constants;
}

/**
 * Returns true when the given ringtone type matches the ringtone to compare.
 * Will default to true if the given ringtone type is RingtoneManager.TYPE_ALL.
 * 
 * @param ringtoneType          ringtone type given
 * @param ringtoneTypeToCompare ringtone type to compare to
 * @return true if the type matches or is TYPE_ALL
 */
private boolean isRingtoneType(int ringtoneType, int ringtoneTypeToCompare) {
    return ringtoneTypeToCompare == ringtoneType || RingtoneManager.TYPE_ALL == ringtoneType;
}
}

FormRingTones

import React from 'react';
import { Text, Button, TouchableOpacity, FlatList, View, ScrollView, StyleSheet,   TouchableHighlight } from 'react-native';
import RingtoneManager from 'react-native-ringtone-manager';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import Slider from 'react-native-slider';
import Sound from 'react-native-sound';
/*
Param   Type    Description
uri     String  The full file path to the ringtone on the file system.
title   String  The title of the ringtone. Will appear in the picker with this title.
artist  String  The artist of the ringtone.
size    Integer     The size of the ringtone file.
mimeType    String  The mime type of the ringtone, for example: audio/mp3
duration    Integer     The duration of the ringtone in seconds.
ringtoneType    RINGTONE_TYPE   The ringtone type: TYPE_ALL, TYPE_RINGTONE,   TYPE_NOTIFICATION, TYPE_ALARM
*/
class MyListItem extends React.PureComponent {
_onPress = () => {
this.props.onPressItem(this.props.datas);
};


render() {
console.log("this.props.uri " + this.props.uri + "this.props.selected " + this.props.selected)
const textColor = this.props.uri === this.props.selected ? 'black' : 'white';
const backgroundColor = this.props.uri === this.props.selected ? 'orange' : '#444444';

return (
  <TouchableOpacity onPress={this._onPress}>
    <View style={{
      backgroundColor: backgroundColor, borderRadius: 14, paddingHorizontal: 10, paddingVertical: 4,marginBottom:4, shadowColor: "#000",
      shadowOffset: {
        width: 0,
        height: 9,
      },
      shadowOpacity: 0.48,
      shadowRadius: 11.95,

      elevation: 18,
    }}>
      <Text style={{ fontSize: 16, color: textColor }}>{this.props.title}</Text>
      <Text style={{ fontSize: 16, color: textColor }}>{this.props.duration}    </Text>
    </View>
  </TouchableOpacity>
 );
 }
}

Result

请参阅有关更新代码的媒体文章:

Ringtone Manager

代码不干净,我将在以后再次处理时更新...

您可以在上看到视频插图:

https://www.youtube.com/watch?v=72UF2ichH8I&feature=youtu.be

(我在网络上的第一个视频:))