Android中Notification的framework层讲解【安卓源码解析四】

 

Android中Notification的framework层讲解【安卓源码解析四】

分类: android源码解析 251人阅读 评论(0) 收藏 举报

             android的notificaiton的声音sound也是申请的AudioManager机制来播放声音的。最近让我找恢复出厂设置后,手机刚启动,接受短信没有声音,如果恢复出厂设置后,等一会儿,过个2分钟再接受短信,就有铃声了。下面我把我分析代码的方法写下来,给自己和读者一些启发:

      日历也是用的是Notification,但是恢复出厂设置后,立马设置日历后,日历可以出声音,我看日历的代码,结果发现日历只是用了Notification的闪屏,真正声音是日历自己实现了Mediaplayer来出声音的。所以我又不得不老老实实地研究Notification.sound到底把声音传递到什么地方去了?

       转载请标明出处:http://blog.csdn.net/wdaming1986/article/details/7081787

       首先我在短信的com.android.mms.transaction包中的MessagingNotification的573行的java代码:notification.sound = TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr);打log查看,发现这个uri确实是存在的,我推测:就是说这个uri传给了framework一层,但是framework一层有没有执行完的动作,所以不响。为了验证是不是短信的错误,我自己单独写了个notification的例子,一个按钮,点击就发出声音。这个例子在正常情况下能正常发声。我就恢复出厂设置后,运行这个例子,结果发现没有声音,这就充分验证了我的猜测。我就去framework去着notificaion.sound = 的声音传递给framework做什么事情了??

       接着,在Source Insight软件中导入framework整个工程,然后搜索,notificaiton.sounds,结果搜到了,在framework/base/core/java/android/app/Notification.java类。

 

  1. /* 
  2.  * Copyright (C) 2007 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package android.app;  
  18.   
  19. import java.util.Date;  
  20.   
  21. import android.app.PendingIntent;  
  22. import android.content.Context;  
  23. import android.content.Intent;  
  24. import android.media.AudioManager;  
  25. import android.net.Uri;  
  26. import android.os.Parcel;  
  27. import android.os.Parcelable;  
  28. import android.text.TextUtils;  
  29. import android.text.format.DateFormat;  
  30. import android.text.format.DateUtils;  
  31. import android.widget.RemoteViews;  
  32.   
  33. /** 
  34.  * A class that represents how a persistent notification is to be presented to 
  35.  * the user using the {@link android.app.NotificationManager}. 
  36.  * 
  37.  * <p>For a guide to creating notifications, see the 
  38.  * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status  
  39.  * Bar Notifications</a> document in the Dev Guide.</p> 
  40.  */  
  41. public class Notification implements Parcelable  
  42. {  
  43.     /** 
  44.      * Use all default values (where applicable). 
  45.      */  
  46.     public static final int DEFAULT_ALL = ~0;  
  47.       
  48.     /** 
  49.      * Use the default notification sound. This will ignore any given 
  50.      * {@link #sound}. 
  51.      *  
  52.      * @see #defaults 
  53.      */   
  54.     public static final int DEFAULT_SOUND = 1;  
  55.   
  56.     /** 
  57.      * Use the default notification vibrate. This will ignore any given 
  58.      * {@link #vibrate}. Using phone vibration requires the  
  59.      * {@link android.Manifest.permission#VIBRATE VIBRATE} permission. 
  60.      *  
  61.      * @see #defaults 
  62.      */   
  63.     public static final int DEFAULT_VIBRATE = 2;  
  64.       
  65.     /** 
  66.      * Use the default notification lights. This will ignore the 
  67.      * {@link #FLAG_SHOW_LIGHTS} bit, and {@link #ledARGB}, {@link #ledOffMS}, or 
  68.      * {@link #ledOnMS}. 
  69.      *  
  70.      * @see #defaults 
  71.      */   
  72.     public static final int DEFAULT_LIGHTS = 4;  
  73.       
  74.     /** 
  75.      * The timestamp for the notification.  The icons and expanded views 
  76.      * are sorted by this key. 
  77.      */  
  78.     public long when;  
  79.   
  80.     /** 
  81.      * The resource id of a drawable to use as the icon in the status bar. 
  82.      */  
  83.     public int icon;  
  84.   
  85.     /** 
  86.      * The number of events that this notification represents.  For example, in a new mail 
  87.      * notification, this could be the number of unread messages.  This number is superimposed over 
  88.      * the icon in the status bar.  If the number is 0 or negative, it is not shown in the status 
  89.      * bar. 
  90.      */  
  91.     public int number;  
  92.   
  93.     /** 
  94.      * The intent to execute when the expanded status entry is clicked.  If 
  95.      * this is an activity, it must include the 
  96.      * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires 
  97.      * that you take care of task management as described in the <em>Activities and Tasks</em> 
  98.      * section of the <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application  
  99.      * Fundamentals</a> document. 
  100.      */  
  101.     public PendingIntent contentIntent;  
  102.   
  103.     /** 
  104.      * The intent to execute when the status entry is deleted by the user 
  105.      * with the "Clear All Notifications" button. This probably shouldn't 
  106.      * be launching an activity since several of those will be sent at the 
  107.      * same time. 
  108.      */  
  109.     public PendingIntent deleteIntent;  
  110.   
  111.     /** 
  112.      * An intent to launch instead of posting the notification to the status bar. 
  113.      * Only for use with extremely high-priority notifications demanding the user's 
  114.      * <strong>immediate</strong> attention, such as an incoming phone call or 
  115.      * alarm clock that the user has explicitly set to a particular time. 
  116.      * If this facility is used for something else, please give the user an option 
  117.      * to turn it off and use a normal notification, as this can be extremely 
  118.      * disruptive. 
  119.      */  
  120.     public PendingIntent fullScreenIntent;  
  121.   
  122.     /** 
  123.      * Text to scroll across the screen when this item is added to 
  124.      * the status bar. 
  125.      */  
  126.     public CharSequence tickerText;  
  127.   
  128.     /** 
  129.      * The view that will represent this notification in the expanded status bar. 
  130.      */  
  131.     public RemoteViews contentView;  
  132.   
  133.     /** 
  134.      * If the icon in the status bar is to have more than one level, you can set this.  Otherwise, 
  135.      * leave it at its default value of 0. 
  136.      * 
  137.      * @see android.widget.ImageView#setImageLevel 
  138.      * @see android.graphics.drawable#setLevel 
  139.      */  
  140.     public int iconLevel;  
  141.   
  142.     /** 
  143.      * The sound to play. 
  144.      *  
  145.      * <p> 
  146.      * To play the default notification sound, see {@link #defaults}.  
  147.      * </p> 
  148.      */  
  149.     public Uri sound;  
  150.   
  151.     /** 
  152.      * Use this constant as the value for audioStreamType to request that 
  153.      * the default stream type for notifications be used.  Currently the 
  154.      * default stream type is STREAM_RING. 
  155.      */  
  156.     public static final int STREAM_DEFAULT = -1;  
  157.   
  158.     /** 
  159.      * The audio stream type to use when playing the sound. 
  160.      * Should be one of the STREAM_ constants from 
  161.      * {@link android.media.AudioManager}. 
  162.      */  
  163.     public int audioStreamType = STREAM_DEFAULT;  
  164.   
  165.       
  166.     /** 
  167.      * The pattern with which to vibrate.  
  168.      *  
  169.      * <p> 
  170.      * To vibrate the default pattern, see {@link #defaults}. 
  171.      * </p> 
  172.      *  
  173.      * @see android.os.Vibrator#vibrate(long[],int) 
  174.      */  
  175.     public long[] vibrate;  
  176.   
  177.     /** 
  178.      * The color of the led.  The hardware will do its best approximation. 
  179.      * 
  180.      * @see #FLAG_SHOW_LIGHTS 
  181.      * @see #flags 
  182.      */  
  183.     public int ledARGB;  
  184.   
  185.     /** 
  186.      * The number of milliseconds for the LED to be on while it's flashing. 
  187.      * The hardware will do its best approximation. 
  188.      * 
  189.      * @see #FLAG_SHOW_LIGHTS 
  190.      * @see #flags 
  191.      */  
  192.     public int ledOnMS;  
  193.   
  194.     /** 
  195.      * The number of milliseconds for the LED to be off while it's flashing. 
  196.      * The hardware will do its best approximation. 
  197.      * 
  198.      * @see #FLAG_SHOW_LIGHTS 
  199.      * @see #flags 
  200.      */  
  201.     public int ledOffMS;  
  202.   
  203.     /** 
  204.      * Specifies which values should be taken from the defaults. 
  205.      * <p> 
  206.      * To set, OR the desired from {@link #DEFAULT_SOUND}, 
  207.      * {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. For all default 
  208.      * values, use {@link #DEFAULT_ALL}. 
  209.      * </p> 
  210.      */  
  211.     public int defaults;  
  212.   
  213.   
  214.     /** 
  215.      * Bit to be bitwise-ored into the {@link #flags} field that should be 
  216.      * set if you want the LED on for this notification. 
  217.      * <ul> 
  218.      * <li>To turn the LED off, pass 0 in the alpha channel for colorARGB 
  219.      *      or 0 for both ledOnMS and ledOffMS.</li> 
  220.      * <li>To turn the LED on, pass 1 for ledOnMS and 0 for ledOffMS.</li> 
  221.      * <li>To flash the LED, pass the number of milliseconds that it should 
  222.      *      be on and off to ledOnMS and ledOffMS.</li> 
  223.      * </ul> 
  224.      * <p> 
  225.      * Since hardware varies, you are not guaranteed that any of the values 
  226.      * you pass are honored exactly.  Use the system defaults (TODO) if possible 
  227.      * because they will be set to values that work on any given hardware. 
  228.      * <p> 
  229.      * The alpha channel must be set for forward compatibility. 
  230.      *  
  231.      */  
  232.     public static final int FLAG_SHOW_LIGHTS        = 0x00000001;  
  233.   
  234.     /** 
  235.      * Bit to be bitwise-ored into the {@link #flags} field that should be 
  236.      * set if this notification is in reference to something that is ongoing, 
  237.      * like a phone call.  It should not be set if this notification is in 
  238.      * reference to something that happened at a particular point in time, 
  239.      * like a missed phone call. 
  240.      */  
  241.     public static final int FLAG_ONGOING_EVENT      = 0x00000002;  
  242.   
  243.     /** 
  244.      * Bit to be bitwise-ored into the {@link #flags} field that if set, 
  245.      * the audio will be repeated until the notification is 
  246.      * cancelled or the notification window is opened. 
  247.      */  
  248.     public static final int FLAG_INSISTENT          = 0x00000004;  
  249.   
  250.     /** 
  251.      * Bit to be bitwise-ored into the {@link #flags} field that should be 
  252.      * set if you want the sound and/or vibration play each time the 
  253.      * notification is sent, even if it has not been canceled before that. 
  254.      */  
  255.     public static final int FLAG_ONLY_ALERT_ONCE    = 0x00000008;  
  256.   
  257.     /** 
  258.      * Bit to be bitwise-ored into the {@link #flags} field that should be 
  259.      * set if the notification should be canceled when it is clicked by the 
  260.      * user.  
  261.      */  
  262.     public static final int FLAG_AUTO_CANCEL        = 0x00000010;  
  263.   
  264.     /** 
  265.      * Bit to be bitwise-ored into the {@link #flags} field that should be 
  266.      * set if the notification should not be canceled when the user clicks 
  267.      * the Clear all button. 
  268.      */  
  269.     public static final int FLAG_NO_CLEAR           = 0x00000020;  
  270.   
  271.     /** 
  272.      * Bit to be bitwise-ored into the {@link #flags} field that should be 
  273.      * set if this notification represents a currently running service.  This 
  274.      * will normally be set for you by {@link Service#startForeground}. 
  275.      */  
  276.     public static final int FLAG_FOREGROUND_SERVICE = 0x00000040;  
  277.   
  278.     public int flags;  
  279.   
  280.     /** 
  281.      * Constructs a Notification object with everything set to 0. 
  282.      */  
  283.     public Notification()  
  284.     {  
  285.         this.when = System.currentTimeMillis();  
  286.     }  
  287.   
  288.     /** 
  289.      * @deprecated use {@link #Notification(int,CharSequence,long)} and {@link #setLatestEventInfo}. 
  290.      * @hide 
  291.      */  
  292.     public Notification(Context context, int icon, CharSequence tickerText, long when,  
  293.             CharSequence contentTitle, CharSequence contentText, Intent contentIntent)  
  294.     {  
  295.         this.when = when;  
  296.         this.icon = icon;  
  297.         this.tickerText = tickerText;  
  298.         setLatestEventInfo(context, contentTitle, contentText,  
  299.                 PendingIntent.getActivity(context, 0, contentIntent, 0));  
  300.     }  
  301.   
  302.     /** 
  303.      * Constructs a Notification object with the information needed to 
  304.      * have a status bar icon without the standard expanded view. 
  305.      * 
  306.      * @param icon          The resource id of the icon to put in the status bar. 
  307.      * @param tickerText    The text that flows by in the status bar when the notification first 
  308.      *                      activates. 
  309.      * @param when          The time to show in the time field.  In the System.currentTimeMillis 
  310.      *                      timebase. 
  311.      */  
  312.     public Notification(int icon, CharSequence tickerText, long when)  
  313.     {  
  314.         this.icon = icon;  
  315.         this.tickerText = tickerText;  
  316.         this.when = when;  
  317.     }  
  318.   
  319.     /** 
  320.      * Unflatten the notification from a parcel. 
  321.      */  
  322.     public Notification(Parcel parcel)  
  323.     {  
  324.         int version = parcel.readInt();  
  325.   
  326.         when = parcel.readLong();  
  327.         icon = parcel.readInt();  
  328.         number = parcel.readInt();  
  329.         if (parcel.readInt() != 0) {  
  330.             contentIntent = PendingIntent.CREATOR.createFromParcel(parcel);  
  331.         }  
  332.         if (parcel.readInt() != 0) {  
  333.             deleteIntent = PendingIntent.CREATOR.createFromParcel(parcel);  
  334.         }  
  335.         if (parcel.readInt() != 0) {  
  336.             tickerText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);  
  337.         }  
  338.         if (parcel.readInt() != 0) {  
  339.             contentView = RemoteViews.CREATOR.createFromParcel(parcel);  
  340.         }  
  341.         defaults = parcel.readInt();  
  342.         flags = parcel.readInt();  
  343.         if (parcel.readInt() != 0) {  
  344.             sound = Uri.CREATOR.createFromParcel(parcel);  
  345.         }  
  346.   
  347.         audioStreamType = parcel.readInt();  
  348.         vibrate = parcel.createLongArray();  
  349.         ledARGB = parcel.readInt();  
  350.         ledOnMS = parcel.readInt();  
  351.         ledOffMS = parcel.readInt();  
  352.         iconLevel = parcel.readInt();  
  353.   
  354.         if (parcel.readInt() != 0) {  
  355.             fullScreenIntent = PendingIntent.CREATOR.createFromParcel(parcel);  
  356.         }  
  357.     }  
  358.   
  359.     public Notification clone() {  
  360.         Notification that = new Notification();  
  361.   
  362.         that.when = this.when;  
  363.         that.icon = this.icon;  
  364.         that.number = this.number;  
  365.   
  366.         // PendingIntents are global, so there's no reason (or way) to clone them.   
  367.         that.contentIntent = this.contentIntent;  
  368.         that.deleteIntent = this.deleteIntent;  
  369.         that.fullScreenIntent = this.fullScreenIntent;  
  370.   
  371.         if (this.tickerText != null) {  
  372.             that.tickerText = this.tickerText.toString();  
  373.         }  
  374.         if (this.contentView != null) {  
  375.             that.contentView = this.contentView.clone();  
  376.         }  
  377.         that.iconLevel = that.iconLevel;  
  378.         that.sound = this.sound; // android.net.Uri is immutable   
  379.         that.audioStreamType = this.audioStreamType;  
  380.   
  381.         final long[] vibrate = this.vibrate;  
  382.         if (vibrate != null) {  
  383.             final int N = vibrate.length;  
  384.             final long[] vib = that.vibrate = new long[N];  
  385.             System.arraycopy(vibrate, 0, vib, 0, N);  
  386.         }  
  387.   
  388.         that.ledARGB = this.ledARGB;  
  389.         that.ledOnMS = this.ledOnMS;  
  390.         that.ledOffMS = this.ledOffMS;  
  391.         that.defaults = this.defaults;  
  392.           
  393.         that.flags = this.flags;  
  394.   
  395.         return that;  
  396.     }  
  397.   
  398.     public int describeContents() {  
  399.         return 0;  
  400.     }  
  401.   
  402.     /** 
  403.      * Flatten this notification from a parcel. 
  404.      */  
  405.     public void writeToParcel(Parcel parcel, int flags)  
  406.     {  
  407.         parcel.writeInt(1);  
  408.   
  409.         parcel.writeLong(when);  
  410.         parcel.writeInt(icon);  
  411.         parcel.writeInt(number);  
  412.         if (contentIntent != null) {  
  413.             parcel.writeInt(1);  
  414.             contentIntent.writeToParcel(parcel, 0);  
  415.         } else {  
  416.             parcel.writeInt(0);  
  417.         }  
  418.         if (deleteIntent != null) {  
  419.             parcel.writeInt(1);  
  420.             deleteIntent.writeToParcel(parcel, 0);  
  421.         } else {  
  422.             parcel.writeInt(0);  
  423.         }  
  424.         if (tickerText != null) {  
  425.             parcel.writeInt(1);  
  426.             TextUtils.writeToParcel(tickerText, parcel, flags);  
  427.         } else {  
  428.             parcel.writeInt(0);  
  429.         }  
  430.         if (contentView != null) {  
  431.             parcel.writeInt(1);  
  432.             contentView.writeToParcel(parcel, 0);  
  433.         } else {  
  434.             parcel.writeInt(0);  
  435.         }  
  436.   
  437.         parcel.writeInt(defaults);  
  438.         parcel.writeInt(this.flags);  
  439.   
  440.         if (sound != null) {  
  441.             parcel.writeInt(1);  
  442.             sound.writeToParcel(parcel, 0);  
  443.         } else {  
  444.             parcel.writeInt(0);  
  445.         }  
  446.         parcel.writeInt(audioStreamType);  
  447.         parcel.writeLongArray(vibrate);  
  448.         parcel.writeInt(ledARGB);  
  449.         parcel.writeInt(ledOnMS);  
  450.         parcel.writeInt(ledOffMS);  
  451.         parcel.writeInt(iconLevel);  
  452.   
  453.         if (fullScreenIntent != null) {  
  454.             parcel.writeInt(1);  
  455.             fullScreenIntent.writeToParcel(parcel, 0);  
  456.         } else {  
  457.             parcel.writeInt(0);  
  458.         }  
  459.     }  
  460.   
  461.     /** 
  462.      * Parcelable.Creator that instantiates Notification objects 
  463.      */  
  464.     public static final Parcelable.Creator<Notification> CREATOR  
  465.             = new Parcelable.Creator<Notification>()  
  466.     {  
  467.         public Notification createFromParcel(Parcel parcel)  
  468.         {  
  469.             return new Notification(parcel);  
  470.         }  
  471.   
  472.         public Notification[] newArray(int size)  
  473.         {  
  474.             return new Notification[size];  
  475.         }  
  476.     };  
  477.   
  478.     /** 
  479.      * Sets the {@link #contentView} field to be a view with the standard "Latest Event" 
  480.      * layout. 
  481.      * 
  482.      * <p>Uses the {@link #icon} and {@link #when} fields to set the icon and time fields 
  483.      * in the view.</p> 
  484.      * @param context       The context for your application / activity. 
  485.      * @param contentTitle The title that goes in the expanded entry. 
  486.      * @param contentText  The text that goes in the expanded entry. 
  487.      * @param contentIntent The intent to launch when the user clicks the expanded notification. 
  488.      * If this is an activity, it must include the 
  489.      * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires 
  490.      * that you take care of task management as described in  
  491.      * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application Fundamentals: Activities and Tasks</a>. 
  492.      */  
  493.     public void setLatestEventInfo(Context context,  
  494.             CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {  
  495.         RemoteViews contentView = new RemoteViews(context.getPackageName(),  
  496.                 com.android.internal.R.layout.status_bar_latest_event_content);  
  497.         if (this.icon != 0) {  
  498.             contentView.setImageViewResource(com.android.internal.R.id.icon, this.icon);  
  499.         }  
  500.         if (contentTitle != null) {  
  501.             contentView.setTextViewText(com.android.internal.R.id.title, contentTitle);  
  502.         }  
  503.         if (contentText != null) {  
  504.             contentView.setTextViewText(com.android.internal.R.id.text, contentText);  
  505.         }  
  506.         if (this.when != 0) {  
  507.             contentView.setLong(com.android.internal.R.id.time, "setTime", when);  
  508.         }  
  509.   
  510.         this.contentView = contentView;  
  511.         this.contentIntent = contentIntent;  
  512.     }  
  513.   
  514.     @Override  
  515.     public String toString() {  
  516.         StringBuilder sb = new StringBuilder();  
  517.         sb.append("Notification(vibrate=");  
  518.         if (this.vibrate != null) {  
  519.             int N = this.vibrate.length-1;  
  520.             sb.append("[");  
  521.             for (int i=0; i<N; i++) {  
  522.                 sb.append(this.vibrate[i]);  
  523.                 sb.append(',');  
  524.             }  
  525.             if (N != -1) {  
  526.                 sb.append(this.vibrate[N]);  
  527.             }  
  528.             sb.append("]");  
  529.         } else if ((this.defaults & DEFAULT_VIBRATE) != 0) {  
  530.             sb.append("default");  
  531.         } else {  
  532.             sb.append("null");  
  533.         }  
  534.         sb.append(",sound=");  
  535.         if (this.sound != null) {  
  536.             sb.append(this.sound.toString());  
  537.         } else if ((this.defaults & DEFAULT_SOUND) != 0) {  
  538.             sb.append("default");  
  539.         } else {  
  540.             sb.append("null");  
  541.         }  
  542.         sb.append(",defaults=0x");  
  543.         sb.append(Integer.toHexString(this.defaults));  
  544.         sb.append(",flags=0x");  
  545.         sb.append(Integer.toHexString(this.flags));  
  546.         sb.append(")");  
  547.         return sb.toString();  
  548.     }  
  549. }  


在344行, sound = Uri.CREATOR.createFromParcel(parcel);回来经过打log发现,问题的关键不再这个类中。

          再次,改变方向,换条思路走,找notification的服务类,看有什么新的发现,在framework/base/services/java/com/android/server/NotificationManagerService.java类中,真的找到了我需要的,


在871行有这句代码:uri = notification.sound;在886行有这句代码:mSound.play(mContext, uri, looping, audioStreamType);当时我就有点兴奋了,感觉这就是问题的关键,然后打log,发现这就是问题的关键,当notification正常发声音的时候,这个886行的代码走进来了,不发声音的时候这个代码没有走进来,所以我离问题的根源又进了一步。最后发现是包着这段代码的if语句中的判断引起的,所以我把if语句中的代码都打印出来,发现是mDisabledNotifications这个变量引起的,我就追踪这个mDisabledNotifications变量值的变化的地方。发现在467行有这段代码:

研究以上的注释,发现原来google故意这么设置的,至于google为什么要这么设置,我没有深究,暂时没有想明白,但是这个这个初始化的时候必须要tsetup wizard (设置向导)运行一次,所以导致了值不对,所以这个notification就不响了。


在264行有这段代码对mDisabledNotification进行改变的:

找到问题的根源了,太兴奋了,这个问题断断续续困扰了我3周,终于经过我3天地认真分析,把问题的根源找到了,要想解决就很简单了,可以在初始化的时候直接赋值为0就ok了!

       最后、886行mSound.play(mContext, uri, looping, audioStreamType);是NotificationPlayer类中的一个方法,在play()方法中有一个线程,  mThread = new CmdThread();   mThread.start();线程中的run方法中有:case   PLAY:startSound(cmd);在startSound()方法中又有一个线程:  mCompletionThread = new CreationAndCompletionThread(cmd);

在这个线程类中的run方法中:在这个线程中进行播放音乐的 ,真正的发声音也是通过Mediapaly来实现的:



 

        希望给读者留下点启发,转载请标明出处:http://blog.csdn.net/wdaming1986/article/details/7081787

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值