如何将本地音频文件设置为ringtone、notifications、alarm等

http://www.xcoder.cn/html/mobile/android/2013/0717/13841.html


最近在做一个小feature,要求用户在设置来电铃音、信息提示音、闹钟铃音、日历提示音时可以浏览本地音频文件(内置或外置SD卡上),并能将本地音频文件设置为相应的铃音或者提示音等。

一、初步分析与最终结果

经过分析发现,系统默认的铃音、提示音等都是直接调用RingtonePreference,点击响应的处理在其onClick()方法中,点击该preference后弹出铃音列表RingtonePickerActivity.java,选中某一铃音点击确定后,将所选结果传回RingtonePreference.java。在RingtonePreference.java的onActivityResult()方法中将设置结果保存并刷新界面。界面展示如下图所示:\

 

因此,如果要求在来电铃音、信息提示音、闹钟铃音、日历提示音时都可以让用户选择浏览本地音频文件或者系统铃音,而这些地方都是直接用的RingtonePreference,那么只有修改RingtonePreference的onClick()方法,即点击preference后弹出一个对话框让用户选择是浏览本地音频文件还是系统铃音。在此,浏览本地文件我们是调用的Music应用的MusicPicker界面,选择本地音频后将结果返回给RingtonePreference。先将完成后的结果展示如下:

\

二、需要修改的文件

要达到上面的效果,并且支持Calendar、Message、AlarmClock关于提示音或铃音的设置,基于android4.2.2源码,需要修改的文件有:

1、frameworks/base/core/java/android/preferences/RingtonePreference.java

2、frameworks/base/core/res/res/values/strings.xml

3、frameworks/base/core/res/res/values/public.xml

4、packages/apps/Calendar/AndroidManifest.xml 增加权限 "android.permission.WRITE_EXTERNAL_STORAGE"

5、packages/apps/Calendar/src/com/android/calendar/GeneralPreferences.java

6、packages/apps/Music/src/com/android/music/MusicPicker.java

7、packages/providers/MediaProvider/src/com/android/providers/media/RingtonePickerActivity.java

8、packages/apps/DeskClock/src/com/android/deskclock/AlarmClock.java

9、packages/apps/DeskClock/res/values/strings.xml

 

具体修改如下(改动较多的就直接贴上整个文件,改动较小的只给出改动部分):

1、frameworks/base/core/java/android/preferences/RingtonePreference.java

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.preference;

import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.app.Activity;
import android.media.RingtoneManager;
import android.net.Uri;
import android.provider.Settings.System;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.provider.MediaStore;
import java.util.ArrayList;
import android.R;

/**
 * A {@link Preference} that allows the user to choose a ringtone from those on the device.
 * The chosen ringtone's URI will be persisted as a string.
 * <p>
 * If the user chooses the "Default" item, the saved string will be one of
 * {@link System#DEFAULT_RINGTONE_URI},
 * {@link System#DEFAULT_NOTIFICATION_URI}, or
 * {@link System#DEFAULT_ALARM_ALERT_URI}. If the user chooses the "Silent"
 * item, the saved string will be an empty string.
 * 
 * @attr ref android.R.styleable#RingtonePreference_ringtoneType
 * @attr ref android.R.styleable#RingtonePreference_showDefault
 * @attr ref android.R.styleable#RingtonePreference_showSilent
 */
public class RingtonePreference extends Preference implements
        PreferenceManager.OnActivityResultListener {

    private static final String TAG = "RingtonePreference";
    
    //added begin
    private static final int MUSIC_PICKER_REQUEST_CODE = 10;
    private static final String RINGTONE_TYPE = "ringtone_type";
    //added  end
    
    private int mRingtoneType;
    private boolean mShowDefault;
    private boolean mShowSilent;
    
    private int mRequestCode;

    public RingtonePreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        
        TypedArray a = context.obtainStyledAttributes(attrs,
                com.android.internal.R.styleable.RingtonePreference, defStyle, 0);
        mRingtoneType = a.getInt(com.android.internal.R.styleable.RingtonePreference_ringtoneType,
                RingtoneManager.TYPE_RINGTONE);
        mShowDefault = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showDefault,
                true);
        mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent,
                true);
        a.recycle();
    }

    public RingtonePreference(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.ringtonePreferenceStyle);
    }
    
    public RingtonePreference(Context context) {
        this(context, null);
    }

    /**
     * Returns the sound type(s) that are shown in the picker.
     * 
     * @return The sound type(s) that are shown in the picker.
     * @see #setRingtoneType(int)
     */
    public int getRingtoneType() {
        return mRingtoneType;
    }

    /**
     * Sets the sound type(s) that are shown in the picker.
     * 
     * @param type The sound type(s) that are shown in the picker.
     * @see RingtoneManager#EXTRA_RINGTONE_TYPE
     */
    public void setRingtoneType(int type) {
        mRingtoneType = type;
    }

    /**
     * Returns whether to a show an item for the default sound/ringtone.
     * 
     * @return Whether to show an item for the default sound/ringtone.
     */
    public boolean getShowDefault() {
        return mShowDefault;
    }

    /**
     * Sets whether to show an item for the default sound/ringtone. The default
     * to use will be deduced from the sound type(s) being shown.
     * 
     * @param showDefault Whether to show the default or not.
     * @see RingtoneManager#EXTRA_RINGTONE_SHOW_DEFAULT
     */
    public void setShowDefault(boolean showDefault) {
        mShowDefault = showDefault;
    }

    /**
     * Returns whether to a show an item for 'Silent'.
     * 
     * @return Whether to show an item for 'Silent'.
     */
    public boolean getShowSilent() {
        return mShowSilent;
    }

    /**
     * Sets whether to show an item for 'Silent'.
     * 
     * @param showSilent Whether to show 'Silent'.
     * @see RingtoneManager#EXTRA_RINGTONE_SHOW_SILENT
     */
    public void setShowSilent(boolean showSilent) {
        mShowSilent = showSilent;
    }

    @Override
    protected void onClick() {
        //modified begin
        AlertDialog.Builder builder = new AlertDialog.Builder(getPreferenceManager().getContext());
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add(getContext().getString(android.R.string.moto_ringtone_preference_choose_action_ringtone));
        arrayList.add(getContext().getString(android.R.string.moto_ringtone_preference_choose_action_music_player));
        CharSequence[] list = arrayList.toArray(new String[arrayList.size()]);
        
        builder.setTitle(android.R.string.moto_ringtone_preference_choose_action);
        builder.setItems(list, new RingtonePreferenceClickListner());
        builder.setNegativeButton(getContext().getString(android.R.string.cancel), new OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.create().show(); 
        //modified end
    }

    /**
     * added
     */
    private class RingtonePreferenceClickListner implements OnClickListener {
        @Override
        public void onClick(DialogInterface dialog, int id) {
            if (id == 1) {
                // add what you sent intent here and add below parameter for
                // music player picker, this will be your onClick()
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.putExtra(RINGTONE_TYPE, mRingtoneType);
                intent.setType("audio/*"); 
                PreferenceFragment owningFragment = getPreferenceManager()
                        .getFragment();
                if (owningFragment != null) {
                    owningFragment.startActivityForResult(intent, MUSIC_PICKER_REQUEST_CODE);
                } else {
                    getPreferenceManager().getActivity()
                            .startActivityForResult(intent, MUSIC_PICKER_REQUEST_CODE);
                }
            } else {
                // add what you sent intent here for default ringtone picker,
                // this will be your onClick()
                Intent intent = new Intent(
                        RingtoneManager.ACTION_RINGTONE_PICKER);
                intent.putExtra(RINGTONE_TYPE, mRingtoneType);
                onPrepareRingtonePickerIntent(intent);
                PreferenceFragment owningFragment = getPreferenceManager()
                        .getFragment();
                if (owningFragment != null) {
                    owningFragment.startActivityForResult(intent, mRequestCode);
                } else {
                    getPreferenceManager().getActivity()
                            .startActivityForResult(intent, mRequestCode);
                }
            }
            dialog.dismiss();
        }
    }
    
    /**
     * Prepares the intent to launch the ringtone picker. This can be modified
     * to adjust the parameters of the ringtone picker.
     * 
     * @param ringtonePickerIntent The ringtone picker intent that can be
     *            modified by putting extras.
     */
    protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {

        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
                onRestoreRingtone());
        
        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault);
        if (mShowDefault) {
            ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
                    RingtoneManager.getDefaultUri(getRingtoneType()));
        }

        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent);
        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, mRingtoneType);
        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getTitle());
    }
    
    /**
     * Called when a ringtone is chosen.
     * <p>
     * By default, this saves the ringtone URI to the persistent storage as a
     * string.
     * 
     * @param ringtoneUri The chosen ringtone's {@link Uri}. Can be null.
     */
    protected void onSaveRingtone(Uri ringtoneUri) {
        persistString(ringtoneUri != null ? ringtoneUri.toString() : "");
    }

    /**
     * Called when the chooser is about to be shown and the current ringtone
     * should be marked. Can return null to not mark any ringtone.
     * <p>
     * By default, this restores the previous ringtone URI from the persistent
     * storage.
     * 
     * @return The ringtone to be marked as the current ringtone.
     */
    protected Uri onRestoreRingtone() {
        final String uriString = getPersistedString(null);
        return !TextUtils.isEmpty(uriString) ? Uri.parse(uriString) : null;
    }
    
    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return a.getString(index);
    }

    @Override
    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValueObj) {
        String defaultValue = (String) defaultValueObj;
        
        /*
         * This method is normally to make sure the internal state and UI
         * matches either the persisted value or the default value. Since we
         * don't show the current value in the UI (until the dialog is opened)
         * and we don't keep local state, if we are restoring the persisted
         * value we don't need to do anything.
         */
        if (restorePersistedValue) {
            return;
        }
        
        // If we are setting to the default value, we should persist it.
        if (!TextUtils.isEmpty(defaultValue)) {
            onSaveRingtone(Uri.parse(defaultValue));
        }
    }

    @Override
    protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
        super.onAttachedToHierarchy(preferenceManager);
        
        preferenceManager.registerOnActivityResultListener(this);
        mRequestCode = preferenceManager.getNextRequestCode();
    }

    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
        //modified begin
        if(data != null){
            int ringtoneType = data.getIntExtra(RINGTONE_TYPE, -1);
            if(ringtoneType == mRingtoneType){
                if (requestCode == mRequestCode){                    
                    Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
                    if (callChangeListener(uri != null ? uri.toString() : "")) {
                        onSaveRingtone(uri);
                    }
                    return true;
                }
                else if(requestCode == MUSIC_PICKER_REQUEST_CODE){
                    Uri uri = data.getData();
                    if (callChangeListener(uri != null ? uri.toString() : "")) {
                        onSaveRingtone(uri);
                        updateItemInExternal(uri);
                    }
                    return true;
                }                
            }
            
        }
        //modified end
        return false;
    }
    
    /**
     * added 
     */
    private void updateItemInExternal(Uri uri){
        ContentValues values = new ContentValues();
        String key = null;
        if(mRingtoneType == RingtoneManager.TYPE_RINGTONE){
            key = MediaStore.Audio.AudioColumns.IS_RINGTONE;
        }
        else if(mRingtoneType == RingtoneManager.TYPE_NOTIFICATION){
            key = MediaStore.Audio.AudioColumns.IS_NOTIFICATION;
        }
        else if(mRingtoneType == RingtoneManager.TYPE_ALARM){
            key = MediaStore.Audio.AudioColumns.IS_ALARM;
        }
        values.put(key, "1");
        getPreferenceManager().getActivity().getContentResolver().update(uri, values, null, null);
    }

}

2、frameworks/base/core/res/res/values/strings.xml

        <!--added for ringtonepreference click event begin -->
        <string name="moto_ringtone_preference_choose_action_ringtone">Ringtones</string>
        <string name="moto_ringtone_preference_choose_action_music_player">Music Player</string>
        <string name="moto_ringtone_preference_choose_action">Choose an action</string>        
        <!--added for ringtonepreference click event end -->

3、frameworks/base/core/res/res/values/public.xml

      <!-- added begin for shown in dialog after ringtone preference click-->
      <public type="string" name="moto_ringtone_preference_choose_action_ringtone" id="0x01040018" />
      <public type="string" name="moto_ringtone_preference_choose_action_music_player" id="0x01040019" />
      <public type="string" name="moto_ringtone_preference_choose_action" id="0x01040020" />
      <!-- added end for shown in dialog after ringtone preference click-->

4、packages/apps/Calendar/AndroidManifest.xml 增加权限 "android.permission.WRITE_EXTERNAL_STORAGE"

       <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

5、packages/apps/Calendar/src/com/android/calendar/GeneralPreferences.java

    @Override
    public void onStop() {
        getPreferenceScreen().getSharedPreferences()
                .unregisterOnSharedPreferenceChangeListener(this);
        mContentResolver.unregisterContentObserver(mObserver);
        /** removed 
         * Calendar ringtonepreference summary don't update after change notification to local file.
        setPreferenceListeners(null);
        */
        super.onStop();
    }
    
    /**
     * added 
     * Calendar ringtonepreference summary don't update after change notification to local file.
     */
    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        setPreferenceListeners(null);
    }

6、packages/apps/Music/src/com/android/music/MusicPicker.java

public class MusicPicker extends ListActivity
        implements View.OnClickListener, MediaPlayer.OnCompletionListener,
        MusicUtils.Defs {
    static final boolean DBG = false;
    static final String TAG = "MusicPicker";
    //added begin
    private static final String RINGTONE_TYPE = "ringtone_type";
    private int mRingtoneType;
    //added end

    …………………………

    
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        int sortMode = TRACK_MENU;
        //added begin
        mRingtoneType = getIntent().getIntExtra(RINGTONE_TYPE, -1);
        //added end

        ………………………

    }

 

    …………………………

 

    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.okayButton:
                if (mSelectedId >= 0) {
                    //modified begin
                    Intent it = new Intent();
                    it.putExtra(RINGTONE_TYPE, mRingtoneType);
                    setResult(RESULT_OK, it.setData(mSelectedUri));
                    //modified end
                    finish();
                }
                break;

            case R.id.cancelButton:
                finish();
                break;
        }
    }

}

7、packages/providers/MediaProvider/src/com/android/providers/media/RingtonePickerActivity.java

public final class RingtonePickerActivity extends AlertActivity implements
        AdapterView.OnItemSelectedListener, Runnable, DialogInterface.OnClickListener,
        AlertController.AlertParams.OnPrepareListViewListener {

    private static final String TAG = "RingtonePickerActivity";
    
    //added begin
    private static final String RINGTONE_TYPE = "ringtone_type";
    private int mRingtoneType;
    //added end

    ……………………

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mHandler = new Handler();

        Intent intent = getIntent();

        /*
         * Get whether to show the 'Default' item, and the URI to play when the
         * default is clicked
         */
        mHasDefaultItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
        mUriForDefaultItem = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI);
        //added begin
        mRingtoneType = intent.getIntExtra(RINGTONE_TYPE, -1);
        //added end

        ……………………

    }

 

    ……………………

 

    /*
     * On click of Ok/Cancel buttons
     */
    public void onClick(DialogInterface dialog, int which) {
        boolean positiveResult = which == DialogInterface.BUTTON_POSITIVE;

        // Stop playing the previous ringtone
        mRingtoneManager.stopPreviousRingtone();

        if (positiveResult) {
            Intent resultIntent = new Intent();
            Uri uri = null;

            if (mClickedPos == mDefaultRingtonePos) {
                // Set it to the default Uri that they originally gave us
                uri = mUriForDefaultItem;
            } else if (mClickedPos == mSilentPos) {
                // A null Uri is for the 'Silent' item
                uri = null;
            } else {
                uri = mRingtoneManager.getRingtoneUri(getRingtoneManagerPosition(mClickedPos));
            }

            resultIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, uri);
            //added begin
            resultIntent.putExtra(RINGTONE_TYPE, mRingtoneType);
            //added end
            setResult(RESULT_OK, resultIntent);
        } else {
            setResult(RESULT_CANCELED);
        }

        getWindow().getDecorView().post(new Runnable() {
            public void run() {
                mCursor.deactivate();
            }
        });

        finish();
    }

}

8、packages/apps/DeskClock/src/com/android/deskclock/AlarmClock.java

public class AlarmClock extends Activity implements LoaderManager.LoaderCallbacks<Cursor>,
        AlarmTimePickerDialogFragment.AlarmTimePickerDialogHandler,
        LabelDialogFragment.AlarmLabelDialogHandler,
        OnLongClickListener, Callback, DialogInterface.OnClickListener {

    ……………………

    //added begin
    private static final int MUSIC_PICKER_REQUEST_CODE = 10;
    private static final String RINGTONE_TYPE = "ringtone_type";
    //added end

    ……………………

 

    private void launchRingTonePicker(Alarm alarm) {
        mSelectedAlarm = alarm;
        //        final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
        //        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, alarm.alert);
        //        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM);
        //        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
        //        startActivityForResult(intent, REQUEST_CODE_RINGTONE);
        //added begin 
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add(getString(R.string.moto_ringtone_preference_choose_action_ringtone));
        arrayList.add(getString(R.string.moto_ringtone_preference_choose_action_music_player));
        CharSequence[] list = arrayList.toArray(new String[arrayList.size()]);
        
        builder.setTitle(R.string.moto_ringtone_preference_choose_action);
        builder.setItems(list, new RingtonePreferenceClickListner());
        builder.setNegativeButton(getString(android.R.string.cancel), new OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.create().show();
        //added end
    }

    

    /**
     * added 
     */
    private class RingtonePreferenceClickListner implements OnClickListener {
        @Override
        public void onClick(DialogInterface dialog, int id) {
            if (id == 1) {
                // add what you sent intent here and add below parameter for
                // music player picker, this will be your onClick()
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.putExtra(RINGTONE_TYPE, RingtoneManager.TYPE_ALARM);
                intent.setType("audio/*"); 
                startActivityForResult(intent, MUSIC_PICKER_REQUEST_CODE);
            } else {
                // add what you sent intent here for default ringtone picker,
                // this will be your onClick()
                Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
                intent.putExtra(RINGTONE_TYPE, RingtoneManager.TYPE_ALARM);
                onPrepareRingtonePickerIntent(intent);
                startActivityForResult(intent, REQUEST_CODE_RINGTONE);
            }
            dialog.dismiss();
        }
    }

 

    /**
     *     added 
     */
    private void onPrepareRingtonePickerIntent(Intent intent) {
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, mSelectedAlarm.alert);
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM);
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
    }
    
    /**
     * modified 
     */
    private void saveRingtoneUri(final Uri uri) {
        mSelectedAlarm.alert = uri;
        // Save the last selected ringtone as the default for new alarms
        RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM, uri);
        asyncUpdateAlarm(mSelectedAlarm, false);
    }

 

    ……………………

 

}

9、packages/apps/DeskClock/res/values/strings.xml

    <!--added by for ringtonepreference click event begin-->
    <string name="moto_ringtone_preference_choose_action_ringtone">Ringtones</string>
    <string name="moto_ringtone_preference_choose_action_music_player">Music Player</string>
    <string name="moto_ringtone_preference_choose_action">Choose an action</string>        
    <!--added for ringtonepreference click event end -->

三、最终需要替换的jar 或者apk

    framework.jar
    framework-res.apk
    Calendar.apk
    Music.apk
    MediaProvider.apk
    DeskClock.apk
要在 Android Studio 音乐播放器使用 Kotlin 文件设置歌曲为铃声,需要经过以下步骤: 1. 在 `AndroidManifest.xml` 文件中添加以下权限: ``` <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ``` 2. 在 Kotlin 文件中添加以下方法,用于将歌曲设置为铃声: ``` private fun setRingtone(filePath: String) { val file = File(filePath) val values = ContentValues() values.put(MediaStore.MediaColumns.DATA, file.absolutePath) values.put(MediaStore.MediaColumns.TITLE, file.name) values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*") values.put(MediaStore.Audio.Media.ARTIST, "artist") values.put(MediaStore.Audio.Media.IS_RINGTONE, true) values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false) values.put(MediaStore.Audio.Media.IS_ALARM, false) values.put(MediaStore.Audio.Media.IS_MUSIC, false) val uri = MediaStore.Audio.Media.getContentUriForPath(file.absolutePath) val newUri = contentResolver.insert(uri, values) RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, newUri) } ``` 这个方法接受一个音乐文件的路径作为参数,然后将该文件设置为系统中的铃声。 3. 在播放器界面中添加一个“设置为铃声”的按钮,点击该按钮时调用上面的方法即可。 ``` button.setOnClickListener { setRingtone(filePath) Toast.makeText(this, "已设置为铃声!", Toast.LENGTH_SHORT).show() } ``` 这里的 `filePath` 是音乐文件的路径,可以根据实际情况进行修改。 完成上述步骤后,用户可以在播放器界面中点击“设置为铃声”按钮将当前播放的歌曲设置为铃声。注意,这个方法需要 WRITE_SETTINGS 权限,因此在 Android 6.0 及以上版本需要动态申请权限。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值