Android系统修改gmail和google日历默认铃声,区别于系统的默认通知音

需求:
单独修改gmail和google日历默认铃声,区别于系统的默认通知音
解决方法:
因为GMS包没有源码,所以无法通过修改apk的方法解决,只能修改获取默认铃声时的uri实现。
具体设计到的文件
/base/media/java/android/media/RingtoneManager.java
/base/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
/base/services/core/java/com/android/server/notification/NotificationManagerService.java
/providers/MediaProvider/src/com/android/providers/media/RingtonePickerActivity.java
在RingtoneManager.java中主要定义读取默认铃声uri的方法


    /**
     * Check the given uri whether exist in device.
     *
     * @param context the context.
     * @param uri the given uri.
     * @return if exist return true, otherwise false.
     * @hide
     * @internal
     */
 	private static String getNotificationUriByName(Context context, String ringname) {
		// TODO Auto-generated method stub
		Cursor cursor = context.getContentResolver().query(
				MediaStore.Audio.Media.INTERNAL_CONTENT_URI,
				new String[] { "_id" }, "_display_name=? and is_notification=1",
				new String[] { ringname }, null);

		int id = 0;
		if (cursor != null) {
			if (cursor.moveToFirst()) {
				do {
					id = cursor.getInt(0);
				} while (cursor.moveToNext());
			}
		}

		Uri ringtoneUri = ContentUris.withAppendedId(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, id);
		if (cursor != null) {
        		cursor.close();
        }

		Log.d(TAG, "getNotificationUriByName ringname = " + ringname + " , ringtoneUri = " + ringtoneUri);
		return ringtoneUri + "";
	}

    /**
     * Check the given uri whether exist in device.
     *
     * @param context the context.
     * @param uri the given uri.
     * @return if exist return true, otherwise false.
     * @hide
     * @internal
     */
 	public static String getNotificationUri(Context context) {

 
        boolean iccid = "1".equals(android.os.SystemProperties.get("persist.operator.subid", "0")) ? true : false;  //Iccid ==1, return true;
        boolean is_op07 =  "OP07".equals(android.os.SystemProperties.get("persist.operator.optr", "")) ? true : false; //op07, return true;
        String mccMnc = android.os.SystemProperties.get("persist.bootanim.mnc", ""); //this is enough for W2100, 334050 or 334090...
        Log.d(TAG, "LCT dual-perso. iccid = " + iccid + ". is_op07 = " + is_op07 + ". mccMnc = " + mccMnc);
		String att_ringtone = null;

       if((is_op07 && ("334090".equals(mccMnc))) || (is_op07 && !iccid && ("334050".equals(mccMnc)))){
    		att_ringtone = getNotificationUriByName(context, "ATT_Email_receive.mp3");
        }
        else{
            att_ringtone = getNotificationUriByName(context, "Success.mp3");
        }
        Log.d(TAG, "ATT -> Calendar default notification uri = " + att_ringtone);
		return att_ringtone;

	}

如果需要获取电话铃声的uri可以把查询条件换成is_ringtone=1

在RingtonePlayer.java中是在用户还没有手动设置过google日历铃声时,有提示音时需要把默认铃声改为指定默认铃声

        public void playAsync(Uri uri, UserHandle user, boolean looping, AudioAttributes aa) {
            if (LOGD) Log.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")");
            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
                throw new SecurityException("Async playback only available from system UID.");
            }
            if (UserHandle.ALL.equals(user)) {
                user = UserHandle.SYSTEM;
            }
            //Added for dt-4590368 by yonglin.liao 2017/05/04 begin {@
			if(android.os.SystemProperties.get("ro.lct.tct_mx_att").equals("1")){
		    	if (uri.toString().contains("android.resource://com.google.android.calendar/raw/")) {

	                String uriString = RingtoneManager.getNotificationUri(mContext);
	                uri = Uri.parse(uriString);
	                Log.d(TAG, "playAsync(Calendar ATT ringtone uri = " + uri + ")");
		            
		        }
			}
		        //Added for dt-4590368 by yonglin.liao 2017/05/04 end @}
		        mAsyncPlayer.play(getContextForUser(user), uri, looping, aa);
		    }

因为google日历的默认铃声是加载的自己内部apk里面的资源,uri比较好识别,但是gmail的默认铃声因为是直接调用的系统默认铃声,所以需要在NotificationManagerService.java中处理notification.sound即可

    void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
            final int callingPid, final String tag, final int id, final Notification notification,
            int[] idOut, int incomingUserId) {
        if (DBG) {
            Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id
                    + " notification" + notification);
        }
		if(android.os.SystemProperties.get("ro.lct.tct_mx_att").equals("1")){
			if(notification.sound != null){
				if(notification.sound.toString().contains("content://settings/system/notification_sound")){
					if(pkg.contains("com.google.android.gm") || pkg.contains("com.tct.email")){
					    String uriString = RingtoneManager.getNotificationUri(getContext());
					    notification.sound = Uri.parse(uriString);
						Log.d(TAG, "notification.sound(Calendar ATT ringtone uri = " + uriString + ")");				
					}
				}
			}
		}

现在在用户还没有设置过默认铃声的情况下,来消息的铃声已经设置成指定的,但是当用户进去铃声列表时默认铃声还是系统的,所以需要在RingtonePickerActivity.java中设置列表的默认选中指定铃声mExistingUri

        mExistingUri = intent
                .getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI);
		Log.d("TAG","mExistingUri -->befor = " + mExistingUri);
        // Added for defect 1278683,1251941 by yonglin.liao on 20160126 begin
		if(android.os.SystemProperties.get("ro.lct.tct_mx_att").equals("1")){
		    if (mExistingUri != null) {
		    	if((mExistingUri + "").contains("android.resource://com.google.android.calendar/raw/") || 
					((mExistingUri + "").contains("content://settings/system/notification_sound") && groundAppPackageName().equals("com.google.android.gm"))) {
		            //Modified for dt-4590368 by yonglin.liao 2017/05/04 begin {@
		            String needChangeCalendarNotification = Settings.System.getString(this.getContentResolver(), "change_calendar_notification");
		            if ((needChangeCalendarNotification != null) && (needChangeCalendarNotification.equals("true"))) {
		                String uriString = Settings.System.getString(this.getContentResolver(), "calendar_att_notification_uri_string");
		                mExistingUri = Uri.parse(uriString);
		                Log.d(TAG, "set mExistingUri = " + mExistingUri);
		            } else {
		                mExistingUri = Settings.System.DEFAULT_NOTIFICATION_URI;
		            }
		            //Modified for dt-4590368 by yonglin.liao 2017/05/04 end @}
		        }
			}
		}
        final AlertController.AlertParams p = mAlertParams;
        p.mCursor = mCursor;

在这个方法中因为调用的是MediaProvider的Activity,传入的context没有实际意义,没法判断google日历的默认铃声,所以我们要想办法获取RingtonePickerActivity上一个Activity是否是google日历,构造方法如下

    private String groundAppPackageName() {
        ActivityManager am = (ActivityManager)getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
        MtkLog.e(TAG, "tasks.get(0).baseActivity.getPackageName() = " + tasks.get(0).baseActivity.getPackageName());
        return tasks.get(0).baseActivity.getPackageName();
    }

现在设置默认铃声基本都已经设置完成,经过编译版本重新下载检查发现一个bug,进去apk的设置铃声页面,默认铃声还是显示系统默认铃声,但是点击进去列表是选中指定铃声
这是因为apk调用了RingtoneManager中Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType)方法,需要对ringtoneUri进行重新赋值成指定铃声

    private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) {
        Log.d(TAG, "getRingtone() ringtoneUri ---> " + ringtoneUri
                   + ", streamType = " + streamType);
		if(android.os.SystemProperties.get("ro.lct.tct_mx_att").equals("1")){
            boolean iccid = "1".equals(android.os.SystemProperties.get("persist.operator.subid", "0")) ? true : false;  //Iccid ==1, return true;
            boolean is_op07 =  "OP07".equals(android.os.SystemProperties.get("persist.operator.optr", "")) ? true : false; //op07, return true;
            String mccMnc = android.os.SystemProperties.get("persist.bootanim.mnc", ""); //this is enough for W2100, 334050 or 334090...
            Log.d(TAG, "LCT dual-perso. iccid = " + iccid + ". is_op07 = " + is_op07 + ". mccMnc = " + mccMnc);

			if(context.getPackageName().equals("com.google.android.gm") || 
				context.getPackageName().equals("com.google.android.calendar") || 
				context.getPackageName().equals("com.tct.email")) {
				String uriString = getNotificationUri(context);
				if((ringtoneUri + "").contains("content://settings/system/notification_sound")){  
			        //Modified for dt-4590368 by yonglin.liao 2017/05/04 begin {@            
		            ringtoneUri = Uri.parse(uriString);
		            Log.d(TAG, "att getRingtone = " + ringtoneUri);
			        //Modified for dt-4590368 by yonglin.liao 2017/05/04 end @}
			    }

				if(is_op07 && iccid && ("334050".equals(mccMnc))){
				    //parameter 3; //OP07 + 334050 + iccid is 1;
					if(isNotificationUri(context,ringtoneUri)) {
						ringtoneUri = Uri.parse(uriString);
					}
				}
				
			}

			if(android.os.SystemProperties.get("ro.lct.tct_mx_att").equals("1")){
			    if(is_op07 && iccid && ("334050".equals(mccMnc))){
			        //parameter 3; //OP07 + 334050 + iccid is 1;
					if(isNotificationUri(context,ringtoneUri)) {
						ringtoneUri = getActualDefaultRingtoneUri(context,TYPE_NOTIFICATION);
					}
			    }
			}


			
		}

        try {
            final Ringtone r = new Ringtone(context, true);
            if (streamType >= 0) {
                r.setStreamType(streamType);
            }
            r.setUri(ringtoneUri);
            return r;
        } catch (Exception ex) {
            Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex);
        }

        return null;
    }

到此为止,整个修改gmail和google日历默认铃声的事情全部完成。如果有其他第三方apk需要修改默认铃声的话,此方法同样生效。

发布了13 篇原创文章 · 获赞 4 · 访问量 4535

猜你喜欢

转载自blog.csdn.net/a785722173/article/details/88879228