欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

[Android]浮層視頻效果,在另外一個Window使用SurfaceV - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當前位置>首頁 » 新聞資訊 » 技術分享 >

[Android]浮層視頻效果,在另外一個Window使用SurfaceV

發(fā)表時間:2020-10-19

發(fā)布人:葵宇科技

瀏覽次數(shù):46


       比來在勞碌視頻的工作,而視頻的繪制須要應用到SurfaceView。為了完成浮層效不雅,我們很天然的想到應用多Window的方法。然則問題就來了,當你將你的SurfaceView放置在別的一個window中的時刻,一切都變得不正常,為了驗證這個器械,我寫了一個小的demo:
       
[img]http://img.blog.csdn.net/20150104122520448?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSGVsbG9fX1plcm8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
     代碼異常簡單,按下中心那個按鈕,彈出一個Window,這個Window瑯綾擎存放一個簡單的SurfaceView,而這個Window的頂層View是一個FrameLayout。Window參數(shù)為:
   
private WindowManager.LayoutParams getWindowLayoutParams() {
        mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
        mWindowLayoutParams.setTitle("This is a test");
        mWindowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        mWindowLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        mWindowLayoutParams.flags
        			|= WindowManager.LayoutParams.FLAG_FULLSCREEN
        			  | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
        mWindowLayoutParams.token = MainActivity.this.getWindow().getDecorView().getWindowToken();
        return mWindowLayoutParams;
    }

好了,我們跑一下,就會發(fā)明界面沒有任何變更,然則界面上的按鈕都弗成點擊。這說清楚明了什么呢?說清楚明了你的Window已經(jīng)被體系窗口治理辦事所接收了,然則,界面顯示出問題。我們給SurfaceView 增長一個SurfaceView回調,并在surfaceCreated處打印Log。你會發(fā)明,這個回調根本沒有走。
@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		Log.v("surface", "surfaceCreated");
	}

這里我插入一灸┞封個回調的感化,這個回調的感化在于告訴你,SurfaceFlinger給你分派的Surface已經(jīng)可用了,然則這個回調不走,意味著當緇ご態(tài)下你的Surface處于弗采取的狀況,也就是SurfaceFlinger給你分派的Surface是弗采取的?;蛟S你到這里已經(jīng)一頭霧水了,不過沒緊要,@非子墨兄剛開端也有點好奇,不過你靜下來再想想,一個過程向SurfaceFlinger申請Surfacce并不是直接申請SurfaceFlinger辦事申請的,而是向WindowManager辦事申請的,也有可能是因為它引起的。我們在整頓一下我們碰到的問題。我們增長了一個Window到窗口治理,然則我們看到了一個透明且沒有surfacceCreate回調的SurfaceView。實際上這是兩個問題:一個問題是透明,一個是沒有回調。
   我們先來解決第一個透明的問題,我們在頂層FrameLayout設置了背景后,發(fā)明照樣透明的,這是為什么呢?是因為SurfaceView這個對象申請顯示區(qū)域的時刻異常特別,并不是跟你的UI線程一個緩沖上疊加繪制,我們可以簡單懂得為它在UI線程所繪制的緩沖上開了個口兒,然后在本身的Buffer膳綾擎繪制。那么怎么解決透明的問題呢?其實異常異常的簡單,只須要給SurfaceView設置一個背景,告訴繪制辦事你的┞封個SurfaceView長短透明的就可以了。我給SurfaceView設置了一個藍色的背景,跑一下不雅然看到了效不雅:




[img]http://img.blog.csdn.net/20150104124346084?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSGVsbG9fX1plcm8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

好了,如許我們解決了第一個問題:透明問題。再次我們來看下第二個問題,SurfaceView不回調的問題。我們剛才對Surface對象無效的問題都純屬于猜測,為了驗證我們的問題我們將SurfaceView中的Surface對象參數(shù)打印一下:
SurfaceView.java:
private void updateWindow(boolean force, boolean redrawNeeded) {
...
relayoutResult = mSession.relayout(
                        mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
                            visible ? VISIBLE : GONE,
                            WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
                            mWinFrame, mOverscanInsets, mContentInsets,
                            mVisibleInsets, mConfiguration, mNewSurface);

/*查看mSurface是否可用*/
booelan result = mSurface.isValid();
...
}
不雅然不出我們所料,result的值為false。我們來看一下mSurface.isValid()的實現(xiàn):

public boolean isValid() {
        synchronized (mLock) {
            if (mNativeObject == 0) return false;
            return nativeIsValid(mNativeObject);
        }
    }

可見,mNativeObject對象句柄為null,也就是體系并沒有分派給你繪制內存句柄。這個時刻,不知道你會不會放棄,告訴本身這是體系的問題,實際上你離本相已經(jīng)很近了,只要再保持一會兒久煨。我們來看一下WMS的log:

W/WindowManager( 1154): Attempted to add window with token that is a sub-window: android.os.BinderProxy@432d6290.  Aborting.
W/WindowManager( 1154): Failed looking up window
W/WindowManager( 1154): java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@43296170 does not exist
W/WindowManager( 1154):         at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7981)
W/WindowManager( 1154):         at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7972)
W/WindowManager( 1154):         at com.android.server.wm.WindowManagerService.relayoutWindow(WindowManagerService.java:2784)
W/WindowManager( 1154):         at com.android.server.wm.Session.relayout(Session.java:190)
W/WindowManager( 1154):         at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:235)
W/WindowManager( 1154):         at com.android.server.wm.Session.onTransact(Session.java:125)
W/WindowManager( 1154):         at android.os.Binder.execTransact(Binder.java:404)
W/WindowManager( 1154):         at dalvik.system.NativeStart.run(Native Method)
W/WindowManager( 1154): Failed looking up window
W/WindowManager( 1154): java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@43296170 does not exist
W/WindowManager( 1154):         at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7981)
W/WindowManager( 1154):         at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7972)
W/WindowManager( 1154):         at com.android.server.wm.WindowManagerService.finishDrawingWindow(WindowManagerService.java:3105)
W/WindowManager( 1154):         at com.android.server.wm.Session.finishDrawing(Session.java:224)
W/WindowManager( 1154):         at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:372)
W/WindowManager( 1154):         at com.android.server.wm.Session.onTransact(Session.java:125)
W/WindowManager( 1154):         at android.os.Binder.execTransact(Binder.java:404)
W/WindowManager( 1154):         at dalvik.system.NativeStart.run(Native Method)

我們粗淺的認為第二個客棧引起的原因是因為第一個客棧,而第一個客棧引起的原因有可能是因為這句話:

W/WindowManager( 1154): Attempted to add window with token that is a sub-window: android.os.BinderProxy@432d6290.  Aborting.
這個其實不算是一個異常,可以當成體系提示,也就是說它將我們的Window當成一個簡單的sub-window。我們看一下WMS這段代碼的實現(xiàn):

public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, InputChannel outInputChannel) {
...
if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
                        && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
                    Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
                            + attrs.token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                }
...
if (addToken) {
                mTokenMap.put(attrs.token, token);
            }
...
}

我們發(fā)明,當你以一個子Window的方法參加一個Window的時刻,體系辦事直接返回,如許就不克不及往mTokenMap中存放你的Token記錄,而這個token不存在,導致了膳綾擎兩個線程的異??蜅?。如許,我們離成功就只有一步之遙,我們已經(jīng)定位我們的問題出在這句話:

mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
而我們只須要改成FIRST_SUB_WINDOW和LAST_SUB_WINDOW之外的值就可以解決問題了。這里我選用了TYPE_TOAST

private WindowManager.LayoutParams getWindowLayoutParams() {
        mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;
        mWindowLayoutParams.setTitle("This is a test");
        mWindowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        mWindowLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        mWindowLayoutParams.flags
        			|= WindowManager.LayoutParams.FLAG_FULLSCREEN
        			  | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
        mWindowLayoutParams.token = MainActivity.this.getWindow().getDecorView().getWindowToken();
        return mWindowLayoutParams;
    }

如許,SurfaceView的回調就正常了,此刻一切問題都水到渠成。欲望這篇文┞仿能贊助到正在做這項功能的筒子們。
thx


         

相關案例查看更多