实现手机来电铃声,通知铃声、警告铃声等音频定制化功能(一,添加扫描分区myimage)

需求功能说明:

该定制需求在各个国家民族差异化为背景下产生的,要求在系统中增加一个新的分区如myimage,用以实现存放定制资源,以符合不同国家民族的用户的体验。例如在myimage下新建media文件夹用于存放定制的音频资源,如果系统myimage分区下,media目录下存在相关目录或文件,则系统摒弃系统重名默认资源,优先选择该分区下的定制资源。

注!

本篇博文结合从系统启动完成之后系统对多媒体文件的扫描流程进行分析和修改。修改思路为:优先扫描定制分区西下定制音频资源并将扫描结果插入相对应的数据库中。若定制分区下不存在资源目录或文件,则将系统默认资源的扫描结果插入相对应的数据库,若定制资源文件名与系统资源文件名相同,则优先插入定制资源。

参考代码:Android4.1.2_r2

1.当系统启动完成,MediaScannerReceiver接收到系统启动完成的广播,并调用scan()方法对内置存储设备进行扫描。

相关类:MediaScannerReceiver.java是一个BroadcastReceiver,接收广播,进行媒体扫描,是MediaScanner提供的接口,主要负责接收广播并启动MediaScannerService具体执行扫描工作。

方法调用流程:onReceiver()-->scan()-->scanDirectories()

具体代码如下:

public voidonReceive(Context context, Intent intent) {

......

if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {//接收到系统启动完成的广播

// 扫描内部存储设备,INTERNAL_VOLUME的值为"internal"

scan(context, MediaProvider.INTERNAL_VOLUME);

}

......

}

private voidscan(Context context, String volume) {

Bundle args = new Bundle();

args.putString("volume", volume);

//通过startService()启动服务开始内部Media文件扫描,这里的参数volume的值为”internal”。

context.startService(new Intent(context, MediaScannerService.class).putExtras(args));

}

2.MediaScannerService服务被启动,主要负责媒体扫描。详细来说MediaScannerService用于接收系统重启后、插拔SD卡、文件复制与拷贝等消息,收到消息后会启动一个handler去处理消息并扫描,最后会将扫描结果放到MediaProvider提供的数据库中去。这里我们先从onCreate生命周期函数开始分析。

主要方法如下:handleMessage()-->scan()

public voidonCreate(){

PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);

//扫描期间保持屏幕常亮

mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);

......

//启动一个工作线程来处理大量的计算任务,由于MediaScannerService实现了Runnable,因此大量计算的任务都是在Runnable的run()方法中来执行的。

Thread thr = new Thread(null, this, "MediaScannerService");

thr.start();

......

}

//在Runnable.run()中执行消息循环,把通过Handler发送过来的消息在工作线程中执行。

public voidrun(){

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_LESS_FAVORABLE);

Looper.prepare();

mServiceLooper = Looper.myLooper();

mServiceHandler = new ServiceHandler();

Looper.loop();

}

//Service对象在被启动的时候,onStartCommand()会被调用。

public intonStartCommand(Intent intent, int flags, int startId){

....

Message msg = mServiceHandler.obtainMessage();

msg.arg1 = startId;

msg.obj = intent.getExtras();

mServiceHandler.sendMessage(msg);

return Service.START_REDELIVER_INTENT;

}

private final classServiceHandlerextends Handler

{

@Override

public void handleMessage(Message msg){

......

Bundle arguments = (Bundle) msg.obj;

String filePath = arguments.getString("filepath");

String volume = arguments.getString("volume");

String[] directories = null;

//根据前文我们知道这里的形参volume的值是“internal”,因此这里会默认扫描"system/media"路径。

if (MediaProvider.INTERNAL_VOLUME.equals(volume)) {

directories = new String[] {

Environment.getRootDirectory() + "/media",

//注:根据需求这里我们新增加了一个新的分区如myimage用来存放我们需要定制的资源,因此在这里我们在对内部进行扫描的时候增加一个扫描路径,也就是“myimage/media”。

"myimage/media"

};

}

if (directories != null) {

......

scan(directories, volume);

......

}

......

}

//从 getContentResolver获得一个ContentResover,然后直接插入根据AIDL,这个ContentResover的另一端是MediaProvider。这里主要获得了一个扫描URI。

private voidscan(String[] directories, String volumeName) {

ContentValues values = new ContentValues();

values.put(MediaStore.MEDIA_SCANNER_VOLUME, volumeName);

Uri scanUri = getContentResolver().insert(MediaStore.getMediaScannerUri(), values);

//这里不做任何修改以保持原有的数据库结构不发生变化。

Uri uri = Uri.parse("file://" + directories[0]);

//发送开始扫描的通知

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_STARTED,
uri));

try {

if (volumeName.equals(MediaProvider.EXTERNAL_VOLUME)) {

openDatabase(volumeName);

}

MediaScanner scanner = createMediaScanner();

//扫描目录

scanner.scanDirectories(directories, volumeName);

} catch (Exception e) {

Log.e(TAG, "exception in MediaScanner.scan()", e);

}

//删除扫描路径,以示扫描结束(这里由于时间问题不做验证,大概也就是会有地方捕捉该删除动作,并发出广播,以通知扫描结束)

getContentResolver().delete(scanUri, null, null);

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_FINISHED,
uri));

mWakeLock.release();

}

时间: 2024-08-08 09:39:12

实现手机来电铃声,通知铃声、警告铃声等音频定制化功能(一,添加扫描分区myimage)的相关文章

安卓手机来电亮屏流程分析

来电亮屏流程分析 本文档是针对手机来电时候自主点亮屏幕这一流程的分析,很自然的就将其分为2个阶段,第一个是来电,第二个是点亮屏幕. 来电的流程: 来电消息是从RIL层接收到的,然后才开始传递上来. AT      : RING AT      : AT< RING AT      : RIL_URC_READER:RING AT      : RIL_URC_READER Enter processLine use-Rlog/RLOG-RIL: Nw URC:RING use-Rlog/RLOG

Android获取手机状态和监听手机来电状态

获取手机状态: import android.content.Context; import android.telephony.TelephonyManager; //获得相应的系统服务 TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); /** * 返回电话状态 * * CALL_STATE_IDLE 无任何状态时 * CALL_STATE_OFFHOOK 接起电话时 *

Android开发之监听手机来电

TelephonyManager是一个管理手机通话状态.电话网络信息的服务类,该类提供了大量的getXxx(),方法获取电话网络的相关信息.关于TelephonyManager的详解可以参照:Android开发之获取手机SIM卡信息 程序运行结果: log_phone文件: 应用实例: package com.jph.monitorphone; import java.io.FileNotFoundException; import java.io.FileOutputStream; impor

Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现(不定期更新中~~~)

系列目录 Unity3D手机斗地主游戏开发实战(01)_发牌功能实现 Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现 一.大体思路 前面我们实现了点击开始游戏按钮,系统依次给玩家发牌的逻辑和动画,并展示当前的手牌.这期我们继续实现接下来的功能--叫地主. 1.首先这两天,学习了DOTween,这是一个强大的Unity动画插件,大家可以参考:官方文档,个人感觉DOTween还是比较好用的. 好的,我们先来重构一下动画部分的代码(没有绝对牛逼的架构和设计,项目过程中不要不断的持续改进嘛

RAD Studio XE8实现手机提示和通知

1.打开XE8,新建Mutli-Device  Form-C++ Builder工程,在Form中加入组件NotificationCenter: 注意:系统通知只能在手机上运行,所以平台要更换为andriod或者iOS等 2.在.cpp中加入头文件 #include<FMX.Platform.hpp> #include<System.IOUtils.hpp> #include<FMX.Notification.hpp> 3.在.h文件中加入GetSoundName()方

Service-监听手机来电

public class MonitorPhone extends Activity { TelephonyManager tManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //取得TelephoneManager对象 tManager = (TelephonyMana

手机影音第七天 视频的播放下一个视频功能实现,视频进度、电量变化的实现

先看下效果图: 在这里,视频进度条会根据视频播放变化,下方的按钮中,播放下一个,上一个都已实现. 代码已经托管到码云上,想下载看的小伙伴可以从下方地址中获取 https://git.oschina.net/joy_yuan/MobilePlayer 1.在这张图上,自定义的显示电量的那一列已经被系统自带的状态栏遮盖,下面就说一下实现方法: 系统电量变化时,系统会发送一个广播,所有对这个广播感兴趣的activity都可以注册广播来接收这个广播.在这里接收系统电量变化,屏幕锁屏.开屏的广播,只能使用

jquery-ui-datepicker定制化,汉化,因手机布局美观化源码修改

感谢浏览,欢迎交流=.= 公司微信网页需要使用日历控件,想到jquery-mobile,但是css影响页面布局,放弃后使用jquery-ui-datepicker. 话不多说,进入正题: 1.jqueryui官网定制化下载jquery-ui. 只取其core+datepicker 则仅需40kb,欣喜一番,因为之前想用dialog功能,发现定制下来150多kb,太奢侈了. 2.汉化代码 (function () { $.datepicker.regional['zh-CN'] = { clear

手游与App测试如何快速转型? —— 过来人科普手游与App测试四大区别

随着智能设备的普及和移动互联网的兴起,各家互联网巨头纷纷在往移动端布局和转型,同时初创的移动互联网公司也都盯着这个市场希望分一杯羹.在这个大环境下,互联网的重心已经慢慢从Web端转向了移动端,而移动端的软件测试也变得越来越重要了. 在移动端的软件里,手游又是其中非常大的一块.从下面的图可以看出,智能手机的普及和手游玩家的增长是密切相关的: 加入鹅厂前,笔者曾经长期从事手机App的测试开发工作.1年前加入鹅厂后转行做了手游测试工作,通过摸索实践,发现两者在相同的测试理论基础之上,其实有着非常不同的