国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

做創(chuàng)意ppt網(wǎng)站有哪些方面網(wǎng)絡seo首頁

做創(chuàng)意ppt網(wǎng)站有哪些方面,網(wǎng)絡seo首頁,企業(yè)微信客戶管理,建設(shè)網(wǎng)站群的意義通常未通過特殊定制的 Android 系統(tǒng),截屏都是經(jīng)過同時按住音量下鍵和電源鍵來截屏。本篇文章就只討論使用這些特殊按鍵來進行截屏。 這里我們就要明白事件是在哪里進行分發(fā)攔截的。通過源碼的分析,我們發(fā)現(xiàn)是在PhoneWindowManager.java 中。 PhoneWindow…

通常未通過特殊定制的 Android 系統(tǒng),截屏都是經(jīng)過同時按住音量下鍵和電源鍵來截屏。本篇文章就只討論使用這些特殊按鍵來進行截屏。
這里我們就要明白事件是在哪里進行分發(fā)攔截的。通過源碼的分析,我們發(fā)現(xiàn)是在PhoneWindowManager.java 中。
PhoneWindowManager#interceptKeyBeforeQueueing()
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    @Overridepublic int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {if (!mSystemBooted) {// If we have not yet booted, don't let key events do anything.return 0;}// 省略部分代碼......// Handle special keys.switch (keyCode) {......case KeyEvent.KEYCODE_VOLUME_DOWN:case KeyEvent.KEYCODE_VOLUME_UP:case KeyEvent.KEYCODE_VOLUME_MUTE: {// 按下音量鍵調(diào)用handleVolumeKey(event, policyFlags);......break;}......case KeyEvent.KEYCODE_POWER: {......if (down) {// 按下電源鍵將調(diào)用interceptPowerKeyDown(event, interactive);} else {          interceptPowerKeyUp(event, interactive, canceled);}break;}}return result;}

1、電源鍵處理

PhoneWindowManager#interceptPowerKeyDown()
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {// 省略部分代碼......// Latch power key state to detect screenshot chord.if (interactive && !mScreenshotChordPowerKeyTriggered&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {// power鍵按下的標志mScreenshotChordPowerKeyTriggered = true;// 獲取 Power 鍵的觸發(fā)時間mScreenshotChordPowerKeyTime = event.getDownTime();// 處理屏幕截圖事件interceptScreenshotChord();// 這個方法應該是消耗、攔截事件的,避免改變音量、鈴聲等。interceptRingerToggleChord();}// 省略部分代碼......}

interceptScreenshotChord()該方法下面再說,先介紹電源按鍵、音量按鍵的處理。

2、音量鍵處理

PhoneWindowManager#handleVolumeKey()
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    public void handleVolumeKey(KeyEvent event, int policyFlags) {final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;final int keyCode = event.getKeyCode();final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {if (down) {// Any activity on the vol down button stops the ringer toggle shortcutcancelPendingRingerToggleChordAction();if (interactive && !mScreenshotChordVolumeDownKeyTriggered&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {// Volume鍵按下的標志mScreenshotChordVolumeDownKeyTriggered = true;// 獲取 Volume 鍵的觸發(fā)時間mScreenshotChordVolumeDownKeyTime = event.getDownTime();// 賦值  false 該屬性為了防止截屏的時候音量下鍵生效出現(xiàn)調(diào)節(jié)音量的 dialog 狀態(tài)值mScreenshotChordVolumeDownKeyConsumed = false;// 防止觸發(fā) Power  鍵長按功能cancelPendingPowerKeyAction();//處理屏幕截圖事件interceptScreenshotChord();// 攔截相關(guān)快捷鍵interceptAccessibilityShortcutChord();}} else {// 省略部分代碼......}} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {// 省略部分代碼......}return;}

3、截屏事件處理 interceptScreenshotChord()

PhoneWindowManager#interceptScreenshotChord()
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    private void interceptScreenshotChord() {/** if 判斷參數(shù)介紹* mScreenshotChordEnabled 其值為mContext.getResources().getBoolean(com.android.internal.R.bool.config_enableScreenshotChord);* mScreenshotChordVolumeDownKeyTriggered 音量下鍵按下時值為true* mScreenshotChordPowerKeyTriggered  電源鍵按下時值為true* mA11yShortcutChordVolumeUpKeyTriggered 音量上(加)鍵抬起時為false , 按下時為true**/if (mScreenshotChordEnabled&& mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered&& !mA11yShortcutChordVolumeUpKeyTriggered) {// 獲取當前時間final long now = SystemClock.uptimeMillis();// 當前時間小于 音量下鍵按下時間 + 150ms// 當前時間小于 power鍵按下時間 + 150msif (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS&& now <= mScreenshotChordPowerKeyTime+ SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {boolean inLongScreenshot = Settings.System.getIntForUser(mContext.getContentResolver(),LONGSCREENSHOT_SETTING, 0, UserHandle.USER_CURRENT_OR_SELF) == 1;if (hasInPowerUtrlSavingMode() || inLongScreenshot) {return;}// 長按音量下鍵,達到截屏條件,將該事件消費掉。mScreenshotChordVolumeDownKeyConsumed = true;// 防止觸發(fā) Power  鍵長按功能cancelPendingPowerKeyAction();// 設(shè)置截圖的類型,TAKE_SCREENSHOT_FULLSCREEN 為全屏mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);// 截圖的方式,(例如:按鍵、三指下滑 等等)mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_CHORD);//執(zhí)行 mScreenshotRunnablemHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());}}}

繼續(xù)查看ScreenshotRunnable,此時會一步步向下調(diào)用,最終到SystemUI。
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    private class ScreenshotRunnable implements Runnable {private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;private int mScreenshotSource = SCREENSHOT_KEY_OTHER;public void setScreenshotType(int screenshotType) {mScreenshotType = screenshotType;}public void setScreenshotSource(int screenshotSource) {mScreenshotSource = screenshotSource;}@Overridepublic void run() {// 回調(diào)到 DisplayPolicy.javamDefaultDisplayPolicy.takeScreenshot(mScreenshotType, mScreenshotSource);}}

DisplayPolicy#takeScreenshot()
frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java

    // 請求截取屏幕截圖public void takeScreenshot(int screenshotType, int source) {if (mScreenshotHelper != null) {mScreenshotHelper.takeScreenshot(screenshotType,mStatusBar != null && mStatusBar.isVisibleLw(),mNavigationBar != null && mNavigationBar.isVisibleLw(),source, mHandler, null /* completionConsumer */);}}

繼續(xù)往下看ScreenshotHelper#takeScreenshot()
frameworks/base/core/java/com/android/internal/util/ScreenshotHelper.java

    // 請求截取屏幕截圖public void takeScreenshot(final int screenshotType, final boolean hasStatus,final boolean hasNav, int source, @NonNull Handler handler,@Nullable Consumer<Uri> completionConsumer) {ScreenshotRequest screenshotRequest = new ScreenshotRequest(source, hasStatus, hasNav);takeScreenshot(screenshotType, SCREENSHOT_TIMEOUT_MS, handler, screenshotRequest,completionConsumer);}//到了 Binder調(diào)用環(huán)節(jié), 此為客戶端, 服務端為SystemUI中的 TakeScreenshotServiceprivate void takeScreenshot(final int screenshotType, long timeoutMs, @NonNull Handler handler,ScreenshotRequest screenshotRequest, @Nullable Consumer<Uri> completionConsumer) {synchronized (mScreenshotLock) {final Runnable mScreenshotTimeout = () -> {synchronized (mScreenshotLock) {if (mScreenshotConnection != null) {// 在獲取屏幕截圖捕獲響應之前超時Log.e(TAG, "Timed out before getting screenshot capture response");// 重置連接resetConnection();// 通知截屏錯誤notifyScreenshotError();}}if (completionConsumer != null) {completionConsumer.accept(null);}};Message msg = Message.obtain(null, screenshotType, screenshotRequest);Handler h = new Handler(handler.getLooper()) {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case SCREENSHOT_MSG_URI:if (completionConsumer != null) {completionConsumer.accept((Uri) msg.obj);}handler.removeCallbacks(mScreenshotTimeout);break;case SCREENSHOT_MSG_PROCESS_COMPLETE:synchronized (mScreenshotLock) {resetConnection();}break;}}};msg.replyTo = new Messenger(h);if (mScreenshotConnection == null || mScreenshotService == null) {// 一個標準的Service連接// config_screenshotServiceComponent == com.android.systemui/com.android.systemui.screenshot.TakeScreenshotServicefinal ComponentName serviceComponent = ComponentName.unflattenFromString(mContext.getResources().getString(com.android.internal.R.string.config_screenshotServiceComponent));final Intent serviceIntent = new Intent();serviceIntent.setComponent(serviceComponent);ServiceConnection conn = new ServiceConnection() {@Override// 當Service連接成功之后public void onServiceConnected(ComponentName name, IBinder service) {synchronized (mScreenshotLock) {if (mScreenshotConnection != this) {return;}mScreenshotService = service;Messenger messenger = new Messenger(mScreenshotService);try {messenger.send(msg);} catch (RemoteException e) {Log.e(TAG, "Couldn't take screenshot: " + e);if (completionConsumer != null) {completionConsumer.accept(null);}}}}@Override// 當Service斷開連接時public void onServiceDisconnected(ComponentName name) {synchronized (mScreenshotLock) {if (mScreenshotConnection != null) {resetConnection();// only log an error if we're still within the timeout periodif (handler.hasCallbacks(mScreenshotTimeout)) {handler.removeCallbacks(mScreenshotTimeout);notifyScreenshotError();}}}}};// bindServiceif (mContext.bindServiceAsUser(serviceIntent, conn,Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,UserHandle.CURRENT)) {mScreenshotConnection = conn;handler.postDelayed(mScreenshotTimeout, timeoutMs);}} else {// 如果已經(jīng)連接則直接發(fā)送MessageMessenger messenger = new Messenger(mScreenshotService);try {messenger.send(msg);} catch (RemoteException e) {Log.e(TAG, "Couldn't take screenshot: " + e);if (completionConsumer != null) {completionConsumer.accept(null);}}handler.postDelayed(mScreenshotTimeout, timeoutMs);}}}

客戶端通過向服務端發(fā)送 message 來將截屏任務交給 service,由 service 處理后面的操作。
frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java

    private Handler mHandler = new Handler(Looper.myLooper()) {@Overridepublic void handleMessage(Message msg) {// 獲取客戶端傳的 Messenger 對象final Messenger callback = msg.replyTo;Consumer<Uri> uriConsumer = uri -> {Message reply = Message.obtain(null, SCREENSHOT_MSG_URI, uri);try {/ /Messenger 雙向通信,在服務端用遠程客戶端的 Messenger 對象給客戶端發(fā)送信息callback.send(reply);} catch (RemoteException e) {}};Runnable onComplete = () -> {Message reply = Message.obtain(null, SCREENSHOT_MSG_PROCESS_COMPLETE);try {callback.send(reply);} catch (RemoteException e) {}};// 判斷用戶的設(shè)備是否為解鎖狀態(tài)// 如果用戶的存儲被鎖定,我們沒有地方存儲截圖,所以跳過它,而不是顯示一個誤導性的動畫和錯誤通知。if (!mUserManager.isUserUnlocked()) {Log.w(TAG, "Skipping screenshot because storage is locked!");post(() -> uriConsumer.accept(null));post(onComplete);return;}ScreenshotHelper.ScreenshotRequest screenshotRequest =(ScreenshotHelper.ScreenshotRequest) msg.obj;mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(screenshotRequest.getSource()));switch (msg.what) {case WindowManager.TAKE_SCREENSHOT_FULLSCREEN:  // 全屏截圖// 我們在PhoneWindowManager傳入的type為全屏截圖,所以需要執(zhí)行全屏截圖流程mScreenshot.takeScreenshot(uriConsumer, onComplete);break;case WindowManager.TAKE_SCREENSHOT_SELECTED_REGION:  // 區(qū)域截圖mScreenshot.takeScreenshot(uriConsumer, onComplete);break;case WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE:Bitmap screenshot = BitmapUtil.bundleToHardwareBitmap(screenshotRequest.getBitmapBundle());Rect screenBounds = screenshotRequest.getBoundsInScreen();Insets insets = screenshotRequest.getInsets();int taskId = screenshotRequest.getTaskId();int userId = screenshotRequest.getUserId();ComponentName topComponent = screenshotRequest.getTopComponent();mScreenshot.handleImageAsScreenshot(screenshot, screenBounds, insets,taskId, userId, topComponent, uriConsumer, onComplete);break;default:Log.d(TAG, "Invalid screenshot option: " + msg.what);}}};

TakeScreenshotService調(diào)用GlobalScreenshot.java的takeScreenshot();
GlobalScreenshot#takeScreenshot()

// GlobalScreenshot.java/***截取當前顯示的屏幕截圖并顯示動畫。.*/private void takeScreenshot(Consumer<Uri> finisher, Rect crop) {// copy the input Rect, since SurfaceControl.screenshot can mutate itRect screenRect = new Rect(crop);int rot = mDisplay.getRotation();int width = crop.width();int height = crop.height();takeScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, screenRect,Insets.NONE, true);}private void takeScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,Insets screenInsets, boolean showFlash) {// 此方法會清除上一次的截圖信息--連續(xù)截圖行為dismissScreenshot("new screenshot requested", true);mScreenBitmap = screenshot;if (mScreenBitmap == null) {// 如果沒有Bitmap則報告錯誤信息mNotificationsController.notifyScreenshotError(R.string.screenshot_failed_to_capture_text);finisher.accept(null);mOnCompleteRunnable.run();return;}if (!isUserSetupComplete()) {// 用戶設(shè)置尚未完成,不應該向用戶展示 分享和編輯 , 只顯示一個Toast并保存圖片saveScreenshotAndToast(finisher);return;}// OptimizationsmScreenBitmap.setHasAlpha(false);mScreenBitmap.prepareToDraw();onConfigChanged(mContext.getResources().getConfiguration());if (mDismissAnimation != null && mDismissAnimation.isRunning()) {mDismissAnimation.cancel();}// 獲取焦點setWindowFocusable(true);// 開始截圖后動畫startAnimation(finisher, screenRect, screenInsets, showFlash);}/*** 截屏后開始動畫*/private void startAnimation(final Consumer<Uri> finisher, Rect screenRect, Insets screenInsets,boolean showFlash) {if (mScreenshotIng == false) {//unisoc: Modify for bug1360276mScreenshotIng = true;// 如果開啟了省電模式,顯示 toast,以便有一些視覺提示已截取屏幕截圖PowerManager powerManager =(PowerManager) mContext . getSystemService (Context.POWER_SERVICE);if (powerManager.isPowerSaveMode()) {Toast.makeText(mContext, R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show();}mScreenshotHandler.post(() -> {if (!mScreenshotLayout.isAttachedToWindow()) {// mScreenshotLayout是截屏的縮略圖的父View// mScreenshotLayout 在 GlobalScreenshot.java 的構(gòu)造方法中初始化。對應布局文件:global_screenshot.xmlmWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);}// 動畫相關(guān)的ViewmScreenshotAnimatedView.setImageDrawable(createScreenDrawable(mScreenBitmap, screenInsets));setAnimatedViewSize(screenRect.width(), screenRect.height());// 顯示動畫何時開始mScreenshotAnimatedView.setVisibility(View.GONE);//縮略圖顯示的View,將native層返回的Bitmap加載到此View上mScreenshotPreview.setImageDrawable(createScreenDrawable(mScreenBitmap, screenInsets));// 使靜態(tài)預覽不可見(消失),以便我們可以在屏幕上查詢其位置mScreenshotPreview.setVisibility(View.INVISIBLE);mScreenshotHandler.post(() -> {mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this);// 創(chuàng)建動畫mScreenshotAnimation =createScreenshotDropInAnimation(screenRect, showFlash);// 保存截圖saveScreenshotInWorkerThread(finisher, new ActionsReadyListener () {@Overridevoid onActionsReady (SavedImageData imageData) {showUiOnActionsReady(imageData);mScreenshotIng = false;}});// 播放快門聲音以通知我們已截屏mCameraSound.play(MediaActionSound.SHUTTER_CLICK);if (mScreenshotPreview.isAttachedToWindow()) {mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);mScreenshotPreview.buildLayer();}// 開始執(zhí)行動畫mScreenshotAnimation.start();});});}}/*** 創(chuàng)建一個新的工作線程并將屏幕截圖保存到媒體存儲*/private void saveScreenshotInWorkerThread(Consumer<Uri> finisher, @Nullable ActionsReadyListener actionsReadyListener) {SaveImageInBackgroundData data = new SaveImageInBackgroundData();data.image = mScreenBitmap;  // native 層返回的 Bitmapdata.finisher = finisher;data.mActionsReadyListener = actionsReadyListener;if (mSaveInBgTask != null) {// just log success/failure for the pre-existing screenshot// 只需記錄預先存在的屏幕截圖的成功失敗mSaveInBgTask.setActionsReadyListener(new ActionsReadyListener() {@Overridevoid onActionsReady(SavedImageData imageData) {logSuccessOnActionsReady(imageData);}});}// 截圖的一些信息存儲在 SaveImageInBackgroundTask 中構(gòu)建mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data);mSaveInBgTask.execute();}

到此截屏流程完畢,可以查看下截圖的View的xml文件:global_screenshot.xml
frameworks/base/packages/SystemUI/res/layout/global_screenshot.xml

<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/global_screenshot_frame"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid:id="@+id/global_screenshot_actions_background"android:layout_height="@dimen/screenshot_bg_protection_height"android:layout_width="match_parent"android:layout_gravity="bottom"android:alpha="0.0"android:src="@drawable/screenshot_actions_background_protection"/><!--截屏動畫相關(guān)的View --><ImageViewandroid:id="@+id/global_screenshot_animated_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="top|start"android:visibility="gone"android:elevation="@dimen/screenshot_preview_elevation"android:background="@drawable/screenshot_rounded_corners" /><ImageViewandroid:id="@+id/global_screenshot_flash"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone"android:elevation="@dimen/screenshot_preview_elevation"android:src="@android:color/white"/><com.android.systemui.screenshot.ScreenshotSelectorViewandroid:id="@+id/global_screenshot_selector"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone"android:pointerIcon="crosshair"/><!-- 此處包含了一個layout, 而縮略圖的View就在此layout中,截屏右上角的關(guān)閉縮略圖按鈕 也在此layout中 --><include layout="@layout/global_screenshot_static"/>
</FrameLayout>
http://aloenet.com.cn/news/44991.html

相關(guān)文章:

  • saas 做網(wǎng)站合肥網(wǎng)絡營銷公司
  • 國外黃岡網(wǎng)站推廣西安發(fā)布最新通知
  • 韓國免費行情網(wǎng)站的推薦理由seo優(yōu)化方式包括
  • 自己組裝電腦做網(wǎng)站服務器不受國內(nèi)限制的瀏覽器
  • 做網(wǎng)站自適應框架他達那非片能延時多久
  • 貴德網(wǎng)站建設(shè)公司專業(yè)網(wǎng)站優(yōu)化
  • 內(nèi)衣網(wǎng)站建設(shè)詳細方案seo官網(wǎng)優(yōu)化詳細方法
  • 大連網(wǎng)站建設(shè)酷網(wǎng)seo網(wǎng)站快速排名外包
  • 鎮(zhèn)江網(wǎng)站建設(shè)yubei021快速建站哪個平臺好
  • 國外做兼職的網(wǎng)站企業(yè)品牌網(wǎng)站營銷
  • wordpress評論樓廣州百度seo排名
  • 如何給網(wǎng)站做宣傳aso優(yōu)化費用
  • 永州做網(wǎng)站費用做百度線上推廣
  • 莆田交友網(wǎng)站市場惠州網(wǎng)站建設(shè)方案推廣
  • 東莞專業(yè)網(wǎng)站建設(shè)推廣seo屬于什么
  • 如何簡述網(wǎng)站建設(shè)流程seo是什么?
  • 網(wǎng)站整體運營思路競價推廣托管服務
  • 車輛對比那個網(wǎng)站做的好免費網(wǎng)絡推廣的方法
  • 昆明利于優(yōu)化的網(wǎng)站河南自助建站seo公司
  • 佛山營銷網(wǎng)站建設(shè)seo快速工具
  • 長春網(wǎng)站建設(shè)58同城想在百度做推廣怎么做
  • 國外做家譜的網(wǎng)站開發(fā)小程序
  • 網(wǎng)站建設(shè)要學會編程嗎網(wǎng)站的營銷推廣方案
  • 國外網(wǎng)站設(shè)計網(wǎng)站昆明百度推廣開戶
  • wordpress 網(wǎng)頁目錄下湖南專業(yè)seo公司
  • 小貸網(wǎng)站需要多少錢可以做seo快速排名優(yōu)化方法
  • 做導航網(wǎng)站犯法嗎web網(wǎng)頁制作教程
  • 教師可以做網(wǎng)站嗎最近熱點新聞事件
  • 寧國做網(wǎng)站優(yōu)化營商環(huán)境的措施建議
  • 網(wǎng)站的域名可以修改嗎做營銷策劃的公司