当前位置: 首页 > news >正文

正在运营的网站被注销备案怎么办潍坊网络科技

正在运营的网站被注销备案怎么办,潍坊网络科技,做saas平台网站,app网站开发流程图前言 当用户点击Android智能设备的按钮的时候#xff0c;如果伴随有按键音效的话#xff0c;会给用户更好的交互体验。本期我们将会结合Android系统源码来具体分析一下控件是如何发出按键音效的。 一、系统加载按键音效资源 1、在TV版的Android智能设备中#xff0c;我们…前言 当用户点击Android智能设备的按钮的时候如果伴随有按键音效的话会给用户更好的交互体验。本期我们将会结合Android系统源码来具体分析一下控件是如何发出按键音效的。 一、系统加载按键音效资源 1、在TV版的Android智能设备中我们可以通过调节设置页面的开关来控制按键音效的有无该设置页面对应的系统源码如下所示。 packages/apps/TvSettings/Settings/src/com/android/tv/settings/device/sound/SoundFragment.java public class SoundFragment extends PreferenceControllerFragment implementsPreference.OnPreferenceChangeListener {private AudioManager mAudioManager;private MapInteger, Boolean mFormats;public static SoundFragment newInstance() {return new SoundFragment();}Overridepublic void onAttach(Context context) {mAudioManager context.getSystemService(AudioManager.class);mFormats mAudioManager.getSurroundFormats();super.onAttach(context);}//用户的点击行为首先触发此方法Overridepublic boolean onPreferenceTreeClick(Preference preference) {if (TextUtils.equals(preference.getKey(), KEY_SOUND_EFFECTS)) {final TwoStatePreference soundPref (TwoStatePreference) preference;//调用setSoundEffectsEnabled来设置按键音的开启与关闭setSoundEffectsEnabled(soundPref.isChecked());}return super.onPreferenceTreeClick(preference);}//获取按键音效是否开启public static boolean getSoundEffectsEnabled(ContentResolver contentResolver) {return Settings.System.getInt(contentResolver, Settings.System.SOUND_EFFECTS_ENABLED, 1)! 0;}//设置是否开启按键音效private void setSoundEffectsEnabled(boolean enabled) {if (enabled) {//如果开启按键音则调用AudioManager的loadSoundEffects方法来加载按键音效资源mAudioManager.loadSoundEffects();} else {mAudioManager.unloadSoundEffects();}Settings.System.putInt(getActivity().getContentResolver(),Settings.System.SOUND_EFFECTS_ENABLED, enabled ? 1 : 0);}}我们在设置页面点击按键音效开关按钮最终会触发SoundFragment的setSoundEffectsEnabled方法该方法会判断是否开启按键音如果开启则调用AudioManager的loadSoundEffects方法来加载按键音效资源反之则会调用unloadSoundEffects方法不加载音效资源。 2、AudioManager的loadSoundEffects方法如下所示。 frameworks/base/media/java/android/media/AudioManager.java public class AudioManager {//获取AudioService的代理对象private static IAudioService getService(){if (sService ! null) {return sService;}IBinder b ServiceManager.getService(Context.AUDIO_SERVICE);sService IAudioService.Stub.asInterface(b);return sService;}public void loadSoundEffects() {final IAudioService service getService();try {//调用AudioService服务的loadSoundEffects方法service.loadSoundEffects();} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}public void unloadSoundEffects() {final IAudioService service getService();try {service.unloadSoundEffects();} catch (RemoteException e) {throw e.rethrowFromSystemServer();}} }AudioManager的首先通过getService方法获取了音频服务AudioService的代理对象然后调用该对象的具体方法。 3、AudioService的loadSoundEffects方法如下所示。 public class AudioService extends IAudioService.Stubimplements AccessibilityManager.TouchExplorationStateChangeListener,AccessibilityManager.AccessibilityServicesStateChangeListener {private AudioHandler mAudioHandler;//加载音效资源public boolean loadSoundEffects() {int attempts 3;LoadSoundEffectReply reply new LoadSoundEffectReply();synchronized (reply) {//调用sendMsg发送消息给mAudioHandler。sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);while ((reply.mStatus 1) (attempts-- 0)) {try {reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);} catch (InterruptedException e) {Log.w(TAG, loadSoundEffects Interrupted while waiting sound pool loaded.);}}}return (reply.mStatus 0);}//不加载音效资源public void unloadSoundEffects() {sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);}private static void sendMsg(Handler handler, int msg,int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {if (existingMsgPolicy SENDMSG_REPLACE) {handler.removeMessages(msg);} else if (existingMsgPolicy SENDMSG_NOOP handler.hasMessages(msg)) {return;}synchronized (mLastDeviceConnectMsgTime) {long time SystemClock.uptimeMillis() delay;if (msg MSG_SET_A2DP_SRC_CONNECTION_STATE ||msg MSG_SET_A2DP_SINK_CONNECTION_STATE ||msg MSG_SET_HEARING_AID_CONNECTION_STATE ||msg MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||msg MSG_A2DP_DEVICE_CONFIG_CHANGE ||msg MSG_BTA2DP_DOCK_TIMEOUT) {if (mLastDeviceConnectMsgTime time) {// add a little delay to make sure messages are ordered as expectedtime mLastDeviceConnectMsgTime 30;}mLastDeviceConnectMsgTime time;}//调用handler的sendMessageAtTime方法handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);}}private class AudioHandler extends Handler {//加载音效private boolean onLoadSoundEffects() {...代码暂时省略...}Overridepublic void handleMessage(Message msg) {switch (msg.what) {...代码省略...case MSG_UNLOAD_SOUND_EFFECTS:onUnloadSoundEffects();//不加载音效break;case MSG_LOAD_SOUND_EFFECTS://加载音效boolean loaded onLoadSoundEffects();//调用onLoadSoundEffects加载音效并将加载结果赋值给loadedif (msg.obj ! null) {LoadSoundEffectReply reply (LoadSoundEffectReply)msg.obj;synchronized (reply) {reply.mStatus loaded ? 0 : -1;reply.notify();}}break;...代码省略...}} }这里我们只要分析一下AudioService的加载音效资源的loadSoundEffects方法该方法会调用sendMsg发送类型为MSG_UNLOAD_SOUND_EFFECTS的msg给mAudioHandler。然后会进一步触发AudioHandler的handleMessage方法该消息最终会触发onLoadSoundEffects方法。 4、AudioHandler的onLoadSoundEffects方法如下所示。 public class AudioService extends IAudioService.Stubimplements AccessibilityManager.TouchExplorationStateChangeListener,AccessibilityManager.AccessibilityServicesStateChangeListener {//音效资源文件名称private static final ListString SOUND_EFFECT_FILES new ArrayListString();private class AudioHandler extends Handler {//加载音效private boolean onLoadSoundEffects() {int status;synchronized (mSoundEffectsLock) {//如果系统未启动完毕直接返回if (!mSystemReady) {Log.w(TAG, onLoadSoundEffects() called before boot complete);return false;}//如果mSoundPool不为空直接返回if (mSoundPool ! null) {return true;}//加载触摸音效loadTouchSoundAssets();...代码暂时省略...}//加载按键音效资源private void loadTouchSoundAssets() {XmlResourceParser parser null;//如果音效资源文件列表不为空直接返回if (!SOUND_EFFECT_FILES.isEmpty()) {return;}//加载按键默认的音效资源loadTouchSoundAssetDefaults();...代码省略...}private void loadTouchSoundAssetDefaults() {//在类型为ListString的SOUND_EFFECT_FILES中添加默认的按键音效资源Effect_Tick.oggSOUND_EFFECT_FILES.add(Effect_Tick.ogg);for (int i 0; i AudioManager.NUM_SOUND_EFFECTS; i) {SOUND_EFFECT_FILES_MAP[i][0] 0;SOUND_EFFECT_FILES_MAP[i][1] -1;}} }onLoadSoundEffects方法首先判断系统是否已经启动完毕如果未启动直接返回然后判断mSoundPool是否空如果不为空则直接返回 然后首先会调用一个关键方法loadTouchSoundAssets该方法首先判断音效资源文件列表SOUND_EFFECT_FILES是否为空不为空直接返回。如果以上判断都不成立则会调用loadTouchSoundAssetDefaults方法加载按键默认的音效资源该方法首先在SOUND_EFFECT_FILES的添加音效资源Effect_Tick.ogg。 5、继续往下看AudioHandler的onLoadSoundEffects方法。 public class AudioService extends IAudioService.Stubimplements AccessibilityManager.TouchExplorationStateChangeListener,AccessibilityManager.AccessibilityServicesStateChangeListener {//音效资源文件名称private static final ListString SOUND_EFFECT_FILES new ArrayListString();private class AudioHandler extends Handler {//加载音效private boolean onLoadSoundEffects() {int status;synchronized (mSoundEffectsLock) {if (!mSystemReady) {Log.w(TAG, onLoadSoundEffects() called before boot complete);return false;}if (mSoundPool ! null) {return true;}//加载触摸音效loadTouchSoundAssets();//创建SoundPool对象mSoundPool new SoundPool.Builder().setMaxStreams(NUM_SOUNDPOOL_CHANNELS).setAudioAttributes(new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build()).build();...代码省略...int numSamples 0;for (int effect 0; effect AudioManager.NUM_SOUND_EFFECTS; effect) {// Do not load sample if this effect uses the MediaPlayerif (SOUND_EFFECT_FILES_MAP[effect][1] 0) {continue;}if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] -1) {//获取音效资源文件路径String filePath getSoundEffectFilePath(effect);//使用SoundPool加载音效资源文件int sampleId mSoundPool.load(filePath, 0);if (sampleId 0) {Log.w(TAG, Soundpool could not load file: filePath);} else {SOUND_EFFECT_FILES_MAP[effect][1] sampleId;poolId[SOUND_EFFECT_FILES_MAP[effect][0]] sampleId;numSamples;}} else {SOUND_EFFECT_FILES_MAP[effect][1] poolId[SOUND_EFFECT_FILES_MAP[effect][0]];}}...代码省略...}//获取音效资源文件路径默认返回的音效资源文件路径为/system/media/audio/ui/Effect_Tick.oggprivate String getSoundEffectFilePath(int effectType) {// /product /media/audio/ui/ Effect_Tick.oggString filePath Environment.getProductDirectory() SOUND_EFFECTS_PATH SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);if (!new File(filePath).isFile()) {// /system /media/audio/ui/ Effect_Tick.oggfilePath Environment.getRootDirectory() SOUND_EFFECTS_PATH SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);}return filePath;}}}onLoadSoundEffects先是调用loadTouchSoundAssets方法加载默认的音效资源文件名称然后构建SoundPool实例对象随后调用getSoundEffectFilePath获取按键音效资源文件路径默认返回的音效资源文件路径为/system/media/audio/ui/Effect_Tick.ogg并调用SoundPool加载该音效资源。 6、简单回顾一下以上步骤。 二、点击控件播放音效资源 在系统开启按键音效之后当我们点击任意控件之后都会触发按键音效。接下来我们将会结合View的系统源码来梳理该流程。 1、当我们点击一个控件的时候首先会触发该View的performClick方法。 frameworks/base/core/java/android/view/View.java public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {public boolean performClick() {// We still need to call this method to handle the cases where performClick() was called// externally, instead of through performClickInternal()notifyAutofillManagerOnClick();final boolean result;final ListenerInfo li mListenerInfo;if (li ! null li.mOnClickListener ! null) {playSoundEffect(SoundEffectConstants.CLICK);//播放按键点击音效li.mOnClickListener.onClick(this);result true;} else {result false;}sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);notifyEnterOrExitForAutoFillIfNeeded(true);return result;}public void playSoundEffect(int soundConstant) {//判断mAttachInfo.mRootCallbacks是否为空以及系统是否开启了按键音效if (mAttachInfo null || mAttachInfo.mRootCallbacks null || !isSoundEffectsEnabled()) {return;}//调用mAttachInfo.mRootCallbacks的playSoundEffect方法mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);}}View的performClick方法会调用playSoundEffect方法playSoundEffect方法首先判断mAttachInfo.mRootCallbacks是否为空以及系统是否开启了按键音效然后调用mAttachInfo.mRootCallbacks的playSoundEffect方法。我们知道WindowManager在将View添加到窗口的过程中都需要用到ViewRootImpl这个类具体请参考Android 9.0系统源码_窗口管理二WindowManager对窗口的管理过程这篇文章。 2、mAttachInfo最初是在ViewRootImpl的构造方法中被创建的。 frameworks/base/core/java/android/view/ViewRootImpl.java public final class ViewRootImpl implements ViewParent,View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {public ViewRootImpl(Context context, Display display) {mContext context;mWindowSession WindowManagerGlobal.getWindowSession();mDisplay display;mBasePackageName context.getBasePackageName();mThread Thread.currentThread();mLocation new WindowLeaked(null);mLocation.fillInStackTrace();mWidth -1;mHeight -1;mDirty new Rect();mTempRect new Rect();mVisRect new Rect();mWinFrame new Rect();mWindow new W(this);mTargetSdkVersion context.getApplicationInfo().targetSdkVersion;mViewVisibility View.GONE;mTransparentRegion new Region();mPreviousTransparentRegion new Region();mFirst true; // true for the first time the view is addedmAdded false;//创建AttachInfo对象倒数第二个参数就是View的playSoundEffect方法所用到的回调对象mAttachInfo new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context);...代码省略...} }3、看完ViewRootImpl的构造方法再来看下AttachInfo的构造方法。 public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {final static class AttachInfo {//关键回调接口interface Callbacks {//播放音效void playSoundEffect(int effectId);boolean performHapticFeedback(int effectId, boolean always);}final Callbacks mRootCallbacks;AttachInfo(IWindowSession session, IWindow window, Display display,ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,Context context) {mSession session;mWindow window;mWindowToken window.asBinder();mDisplay display;mViewRootImpl viewRootImpl;mHandler handler;mRootCallbacks effectPlayer;//View的playSoundEffect方法所用到的回调对象就是这个mTreeObserver new ViewTreeObserver(context);}}}AttachInfo构造方法的最后一个参数很关键因为View的playSoundEffect方法所调用的对象就是这个结合ViewRootImpl的代码我们可以知道是ViewRootImpl实现了这个回调。 4、ViewRootImpl的playSoundEffect方法如下所示。 public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {public void playSoundEffect(int effectId) {checkThread();//检测是否是UI线程try {final AudioManager audioManager getAudioManager();switch (effectId) {case SoundEffectConstants.CLICK://播放按键点击音效audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);return;case SoundEffectConstants.NAVIGATION_DOWN:audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);return;case SoundEffectConstants.NAVIGATION_LEFT:audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);return;case SoundEffectConstants.NAVIGATION_RIGHT:audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);return;case SoundEffectConstants.NAVIGATION_UP:audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);return;default:throw new IllegalArgumentException(unknown effect id effectId not defined in SoundEffectConstants.class.getCanonicalName());}} catch (IllegalStateException e) {// Exception thrown by getAudioManager() when mView is nullLog.e(mTag, FATAL EXCEPTION when attempting to play sound effect: e);e.printStackTrace();}} }ViewRootImpl的playSoundEffect方法首先会检测一下当前线程是不是UI线程然后会根据传入的effectId类型来判断要播放那种音效。因为View的performClick方法传入的是SoundEffectConstants.CLICK所以会触发audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK)。 4、AudioManager的playSoundEffect方法如下所示。 public class AudioManager {public void playSoundEffect(int effectType) {//检测音效类型是否合规if (effectType 0 || effectType NUM_SOUND_EFFECTS) {return;}//确定音效是否可用if (!querySoundEffectsEnabled(Process.myUserHandle().getIdentifier())) {return;}//获取AudioService服务final IAudioService service getService();try {//调用服务的playSoundEffect方法service.playSoundEffect(effectType);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}/*** Settings has an in memory cache, so this is fast.*/private boolean querySoundEffectsEnabled(int user) {return Settings.System.getIntForUser(getContext().getContentResolver(),Settings.System.SOUND_EFFECTS_ENABLED, 0, user) ! 0;} }AudioManager的playSoundEffect会做一些校验如果校验通过则会获取AudioService服务对象并调用该对象的playSoundEffect方法进行音效播放。 5、AudioService和playSoundEffect相关的代码如下所示。 public class AudioService extends IAudioService.Stubimplements AccessibilityManager.TouchExplorationStateChangeListener,AccessibilityManager.AccessibilityServicesStateChangeListener {/*** 播放音效* param effectType*/public void playSoundEffect(int effectType) {playSoundEffectVolume(effectType, -1.0f);}public void playSoundEffectVolume(int effectType, float volume) {// do not try to play the sound effect if the system stream is mutedif (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {return;}if (effectType AudioManager.NUM_SOUND_EFFECTS || effectType 0) {Log.w(TAG, AudioService effectType value effectType out of range);return;}//发送播放音效的消息给mAudioHandlersendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,effectType, (int) (volume * 1000), null, 0);}private class AudioHandler extends Handler {//加载音效private boolean onLoadSoundEffects() {...代码暂时省略...}Overridepublic void handleMessage(Message msg) {switch (msg.what) {...代码省略...case MSG_UNLOAD_SOUND_EFFECTS:onUnloadSoundEffects();//不加载音效break;case MSG_LOAD_SOUND_EFFECTS://加载音效boolean loaded onLoadSoundEffects();//调用onLoadSoundEffects加载音效并将加载结果赋值给loaded...代码省略...break;case MSG_PLAY_SOUND_EFFECT://播放音效onPlaySoundEffect(msg.arg1, msg.arg2);break;...代码省略...}} }AudioService的playSoundEffect方法进一步调用playSoundEffectVolume该方法会发送播放音效的消息MSG_PLAY_SOUND_EFFECT给mAudioHandler最终会触发onPlaySoundEffect方法。 6、AudioService的onPlaySoundEffec方法如下所示。 public class AudioService extends IAudioService.Stubimplements AccessibilityManager.TouchExplorationStateChangeListener,AccessibilityManager.AccessibilityServicesStateChangeListener {private void onPlaySoundEffect(int effectType, int volume) {synchronized (mSoundEffectsLock) {onLoadSoundEffects();//加载音效if (mSoundPool null) {return;}float volFloat;// use default if volume is not specified by callerif (volume 0) {volFloat (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);} else {volFloat volume / 1000.0f;}if (SOUND_EFFECT_FILES_MAP[effectType][1] 0) {//通过SoundPool播放音效mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],volFloat, volFloat, 0, 0, 1.0f);} else {//通过MediaPlayer播放音效MediaPlayer mediaPlayer new MediaPlayer();try {String filePath getSoundEffectFilePath(effectType);mediaPlayer.setDataSource(filePath);mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);mediaPlayer.prepare();mediaPlayer.setVolume(volFloat);mediaPlayer.setOnCompletionListener(new OnCompletionListener() {public void onCompletion(MediaPlayer mp) {cleanupPlayer(mp);}});mediaPlayer.setOnErrorListener(new OnErrorListener() {public boolean onError(MediaPlayer mp, int what, int extra) {cleanupPlayer(mp);return true;}});mediaPlayer.start();} catch (IOException ex) {Log.w(TAG, MediaPlayer IOException: ex);} catch (IllegalArgumentException ex) {Log.w(TAG, MediaPlayer IllegalArgumentException: ex);} catch (IllegalStateException ex) {Log.w(TAG, MediaPlayer IllegalStateException: ex);}}}}}7、简单回顾一下以上步骤。
http://www.w-s-a.com/news/218913/

相关文章:

  • 织梦cms 官方网站网页视频如何下载到电脑
  • 查询建设公司业绩网站国外外链平台
  • 搭建直播网站需要怎么做做石材网站步骤
  • 移动网站如何做权重wordpress 统计字数 插件
  • 编写网站的软件百度指数教程
  • 网站改版建议策划书做设计什么兼职网站
  • 北京做兼职网站文创产品设计流程
  • 南阳做玉器网站wordpress 图片被缩小
  • 自己做网站卖衣服cms做网站容易不
  • 安徽安搜做的网站怎么样手机网站商城建设答辩问题
  • 分析不同网站的优缺点房产网站定制
  • 深圳工业设计大展2021论坛与网站做优化哪个更好
  • 什么网站做招聘比较好网络营销渠道管理
  • 网站建设选择什么模式淘宝网站可以做轮播吗
  • 山西免费网站制作乌市高新区建设局网站
  • 公司网站建设费用会计处理手机app免费下载
  • 网站的做网站的公司网站有些什么内容
  • 网站新类型wordpress 随机文章
  • 电商网站建设会计分录朝阳市网站公司
  • 正邦网站建设 优帮云百姓网征婚
  • 企业网站有哪些举几个例子端午节网站建设目的
  • 南京免费发布信息网站网站建设与管理职责
  • 无锡市建设培训中心网站企业vi设计是啥
  • 宿松网站建设推荐秒搜科技国家官方网站
  • 网站的服务器选择wordpress文章底部加分享
  • 天津专业的网站建设公司阿里云服务器 wordpress
  • 家教辅导培训网站建设中东跨境电商平台有哪些
  • 商城形式的网站需要多少钱做医药商城网站的公司吗
  • 贵阳网站设计zu97彩票创建网站
  • 网站建设与分工的论文足球世界排名