<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【Android】基于SurfaceControlViewHost實(shí)現(xiàn)跨進(jìn)程渲染

      1 前言

      ? 本文將介紹基于 SurfaceControlViewHost 實(shí)現(xiàn)跨進(jìn)程渲染普通 View 和 GlSurfaceView,力求用最簡單的 Demo,介紹 SurfaceControlViewHost 的應(yīng)用,方便讀者輕松扣出核心代碼應(yīng)用到自己的業(yè)務(wù)中。

      ? 核心代碼片段如下。

      ? 1)服務(wù)端

      public SurfaceControlViewHost.SurfacePackage getSurfacePackage(int displayId, IBinder hostToken, int width, int height) {
          // 創(chuàng)建SurfaceControlViewHost
          Display display = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
          mSurfaceControlViewHost = new SurfaceControlViewHost(mContext, display, hostToken);
          // 創(chuàng)建要渲染的View
          mView = new CustomView(mContext);
          // 將View附加到SurfaceControlViewHost
          mSurfaceControlViewHost.setView(mView, width, height);
          SurfacePackage surfacePackage = mSurfaceControlViewHost.getSurfacePackage();
          return surfacePackage;
      }
      

      ? 2)客戶端

      IBinder hostToken = mSurfaceView.getHostToken();
      SurfaceControlViewHost.SurfacePackage surfacePackage = mRemoteRender.getSurfacePackage(0, hostToken, 1000, 2000);
      mSurfaceView.setChildSurfacePackage(surfacePackage);
      

      ? 本文案例項(xiàng)目結(jié)構(gòu)如下,完整資源見 → 基于SurfaceControlViewHost實(shí)現(xiàn)跨進(jìn)程渲染

      img

      2 AIDL 配置

      ? Android 跨進(jìn)程通信可以使用 AIDLmessenger,它們本質(zhì)都是 Binder,本文使用 AIDL 實(shí)現(xiàn)跨進(jìn)程通信。

      ? 1)aidl 文件

      // IRemoteRender.aidl
      package com.zhyan8.remoterender;
      
      import android.view.SurfaceControlViewHost.SurfacePackage;
      import android.os.IBinder;
      
      interface IRemoteRender {
          SurfacePackage getSurfacePackage(int displayId, IBinder hostToken, int width, int height);
      }
      

      ? 2)gradle 配置

      sourceSets {
          main {
              aidl.srcDirs = ['src/main/aidl']
          }
      }
      
      buildFeatures.aidl true
      

      ? 3)manifest 配置

      ? 客戶端配置如下。

      <queries>
          <package android:name="com.zhyan8.service" />
          <package android:name="com.zhyan8.glservice" />
      </queries>
      

      ? 服務(wù)端配置如下。

      <service
          android:name=".RemoteRenderService"
          android:exported="true">
          <intent-filter>
              <action android:name="com.zhyan8.remoterender.IRemoteRender"/>
          </intent-filter>
      </service>
      
      <service
          android:name=".RemoteGLRenderService"
          android:exported="true">
          <intent-filter>
              <action android:name="com.zhyan8.remoterender.IRemoteRender"/>
          </intent-filter>
      </service>
      

      3 客戶端

      ? MainActivity.java

      package com.zhyan8.client;
      
      import android.content.ComponentName;
      import android.content.Context;
      import android.content.Intent;
      import android.content.ServiceConnection;
      import android.os.Bundle;
      import android.os.IBinder;
      import android.os.RemoteException;
      import android.util.Log;
      import android.view.SurfaceControlViewHost.SurfacePackage;
      import android.view.SurfaceView;
      import android.view.View;
      
      import androidx.appcompat.app.AppCompatActivity;
      
      import com.zhyan8.remoterender.IRemoteRender;
      
      public class MainActivity extends AppCompatActivity {
          private static final String TAG = "MainActivity";
      
          private IRemoteRender mRemoteRender;
          private IBinder mService;
          private SurfaceView mSurfaceView;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              mSurfaceView = findViewById(R.id.surface_view);
              startService();
          }
      
          public void onClickDraw(View view) {
              try {
                  IBinder hostToken = mSurfaceView.getHostToken();
                  SurfacePackage surfacePackage = mRemoteRender.getSurfacePackage(0, hostToken, 1000, 2000);
                  mSurfaceView.setChildSurfacePackage(surfacePackage);
              } catch (RemoteException e) {
                  e.printStackTrace();
              }
          }
      
          @Override
          protected void onDestroy() {
              super.onDestroy();
              unbindService(mConnection);
          }
      
          private void startService() {
              Log.d(TAG, "startService");
              Intent intent = new Intent("com.zhyan8.remoterender.IRemoteRender");
              //intent.setPackage("com.zhyan8.service"); // 渲染普通View的服務(wù)
              intent.setPackage("com.zhyan8.glservice"); // 基于OpenGL ES渲染的服務(wù)
              bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
          }
      
          private void clearBind() {
              Log.d(TAG, "clearBind");
              if (mService != null) {
                  mService.unlinkToDeath(mDeathRecipient, 0);
              }
              mRemoteRender = null;
              mService = null;
          }
      
          private ServiceConnection mConnection = new ServiceConnection() {
              @Override
              public void onServiceConnected(ComponentName name, IBinder service) {
                  Log.d(TAG, "onServiceConnected");
                  mRemoteRender = IRemoteRender.Stub.asInterface(service);
                  mService = service;
                  try {
                      mService.linkToDeath(mDeathRecipient, 0);
                  } catch (RemoteException e) {
                      Log.e(TAG, "e=" + e.getMessage());
                  }
              }
      
              @Override
              public void onServiceDisconnected(ComponentName name) {
                  Log.d(TAG, "onServiceDisconnected");
                  clearBind();
              }
          };
      
          private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
      
              @Override
              public void binderDied() {
                  Log.d(TAG, "binderDied");
                  clearBind();
              }
          };
      }
      

      ? activity_main.xml

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical"
          android:padding="16dp">
      
          <Button
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="draw"
              android:onClick="onClickDraw"/>
      
          <android.view.SurfaceView
              android:id="@+id/surface_view"
              android:layout_width="1000px"
              android:layout_height="2000px"
              android:layout_gravity="center"/>
      </LinearLayout>
      

      4 跨進(jìn)程渲染普通 View

      ? RemoteRenderService.java

      package com.zhyan8.service;
      
      import android.app.Service;
      import android.content.Context;
      import android.content.Intent;
      import android.hardware.display.DisplayManager;
      import android.os.Handler;
      import android.os.IBinder;
      import android.os.Looper;
      import android.util.Log;
      import android.view.Display;
      import android.view.SurfaceControlViewHost;
      import android.view.SurfaceControlViewHost.SurfacePackage;
      import android.view.ViewGroup;
      import android.widget.ImageView;
      
      import com.zhyan8.remoterender.IRemoteRender;
      
      import java.util.concurrent.CountDownLatch;
      
      public class RemoteRenderService extends Service {
          private static final String TAG = "RemoteRenderService";
      
          private SurfaceControlViewHost mSurfaceControlViewHost;
          private ImageView mImageView;
          private Handler mHandler = new Handler(Looper.getMainLooper());
      
          @Override
          public void onCreate() {
              super.onCreate();
              Log.i(TAG, "onCreate");
          }
      
          @Override
          public IBinder onBind(Intent intent) {
              Log.i(TAG, "onBind");
              return mBinder;
          }
      
          @Override
          public void onDestroy() {
              super.onDestroy();
              Log.i(TAG, "onDestroy");
              if (mSurfaceControlViewHost != null) {
                  mSurfaceControlViewHost.release();
              }
          }
      
          private final IRemoteRender.Stub mBinder = new IRemoteRender.Stub() {
      
              @Override
              public SurfacePackage getSurfacePackage(int displayId, IBinder hostToken, int width, int height) {
                  Log.i(TAG, "getSurfacePackage, displayId=" + displayId + ", hostToken=" + hostToken + ", width=" + width + ", height=" + height);
                  final SurfacePackage[] result = new SurfaceControlViewHost.SurfacePackage[1];
                  final CountDownLatch latch = new CountDownLatch(1);
                  mHandler.post( () -> {
                      // 創(chuàng)建SurfaceControlViewHost
                      Context context = getBaseContext();
                      Display display = context.getSystemService(DisplayManager.class).getDisplay(displayId);
                      mSurfaceControlViewHost = new SurfaceControlViewHost(context, display, hostToken);
                      // 創(chuàng)建要渲染的內(nèi)容
                      mImageView = new ImageView(RemoteRenderService.this);
                      mImageView.setLayoutParams(new ViewGroup.LayoutParams(width, height));
                      mImageView.setScaleType(ImageView.ScaleType.FIT_XY);
                      mImageView.setImageResource(R.drawable.girl);
                      // 將視圖附加到SurfaceControlViewHost
                      mSurfaceControlViewHost.setView(mImageView, width, height);
                      result[0] = mSurfaceControlViewHost.getSurfacePackage();
                      latch.countDown();
                  });
      
                  try {
                      latch.await(); // 等待主線程完成操作
                      return result[0];
                  } catch (InterruptedException e) {
                      Log.i(TAG, "getSurfacePackage, e=" + e.getMessage());
                  }
                  return null;
              }
          };
      }
      

      ? 運(yùn)行效果如下。

      img

      5 跨進(jìn)程渲染 GLSurfaceView

      ? RemoteGLRenderService.java

      package com.zhyan8.glservice;
      
      import android.app.Service;
      import android.content.Context;
      import android.content.Intent;
      import android.hardware.display.DisplayManager;
      import android.opengl.GLSurfaceView;
      import android.os.Handler;
      import android.os.IBinder;
      import android.os.Looper;
      import android.util.Log;
      import android.view.Display;
      import android.view.SurfaceControlViewHost;
      import android.view.SurfaceControlViewHost.SurfacePackage;
      import android.view.ViewGroup;
      
      import com.zhyan8.remoterender.IRemoteRender;
      
      import java.util.concurrent.CountDownLatch;
      
      public class RemoteGLRenderService extends Service {
          private static final String TAG = "RemoteGLRenderService";
      
          private SurfaceControlViewHost mSurfaceControlViewHost;
          private GLSurfaceView mGLSurfaceView;
          private Handler mHandler = new Handler(Looper.getMainLooper());
      
          @Override
          public void onCreate() {
              super.onCreate();
              Log.i(TAG, "onCreate");
          }
      
          @Override
          public IBinder onBind(Intent intent) {
              Log.i(TAG, "onBind");
              return mBinder;
          }
      
          @Override
          public void onDestroy() {
              Log.i(TAG, "onDestroy");
              super.onDestroy();
              if (mSurfaceControlViewHost != null) {
                  mSurfaceControlViewHost.release();
              }
          }
      
          private final IRemoteRender.Stub mBinder = new IRemoteRender.Stub() {
      
              @Override
              public SurfacePackage getSurfacePackage(int displayId, IBinder hostToken, int width, int height) {
                  Log.i(TAG, "getSurfacePackage, displayId=" + displayId + ", hostToken=" + hostToken + ", width=" + width + ", height=" + height);
                  final SurfacePackage[] result = new SurfaceControlViewHost.SurfacePackage[1];
                  final CountDownLatch latch = new CountDownLatch(1);
                  mHandler.post( () -> {
                      // 創(chuàng)建SurfaceControlViewHost
                      Context context = getBaseContext();
                      Display display = context.getSystemService(DisplayManager.class).getDisplay(displayId);
                      mSurfaceControlViewHost = new SurfaceControlViewHost(context, display, hostToken);
                      // 創(chuàng)建要渲染的內(nèi)容
                      mGLSurfaceView = new GLSurfaceView(RemoteGLRenderService.this);
                      mGLSurfaceView.setEGLContextClientVersion(3);
                      mGLSurfaceView.setLayoutParams(new ViewGroup.LayoutParams(width, height));
                      mGLSurfaceView.setRenderer(new MyGLRenderer(RemoteGLRenderService.this));
                      // 將視圖附加到SurfaceControlViewHost
                      mSurfaceControlViewHost.setView(mGLSurfaceView, width, height);
                      result[0] = mSurfaceControlViewHost.getSurfacePackage();
                      latch.countDown();
                  });
      
                  try {
                      latch.await(); // 等待主線程完成操作
                      return result[0];
                  } catch (InterruptedException e) {
                      Log.i(TAG, "getSurfacePackage, e=" + e.getMessage());
                  }
                  return null;
              }
          };
      }
      

      ? MyGLRenderer.java

      package com.zhyan8.glservice;
      
      import android.opengl.GLES30;
      import android.opengl.GLSurfaceView;
      
      import javax.microedition.khronos.egl.EGLConfig;
      import javax.microedition.khronos.opengles.GL10;
      
      import android.content.Context;
      
      import java.nio.FloatBuffer;
      
      public class MyGLRenderer implements GLSurfaceView.Renderer {
          private FloatBuffer vertexBuffer;
          private FloatBuffer textureBuffer;
          private MyGLUtils mGLUtils;
          private int mTextureId;
          private int mTimeLocation;
          private long mStartTime = 0L;
          private long mRunTime = 0L;
      
          public MyGLRenderer(Context context) {
              mGLUtils = new MyGLUtils(context);
              getFloatBuffer();
              mStartTime = System.currentTimeMillis();
          }
      
          @Override
          public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
              //設(shè)置背景顏色
              GLES30.glClearColor(0.1f, 0.2f, 0.3f, 0.4f);
              //編譯著色器
              final int vertexShaderId = mGLUtils.compileShader(GLES30.GL_VERTEX_SHADER, R.raw.vertex_shader);
              final int fragmentShaderId = mGLUtils.compileShader(GLES30.GL_FRAGMENT_SHADER, R.raw.fragment_shader);
              //鏈接程序片段
              int programId = mGLUtils.linkProgram(vertexShaderId, fragmentShaderId);
              GLES30.glUseProgram(programId);
              mTextureId = mGLUtils.loadTexture(R.drawable.girl);
              mTimeLocation = GLES30.glGetUniformLocation(programId, "u_time");
          }
      
          @Override
          public void onSurfaceChanged(GL10 gl, int width, int height) {
              //設(shè)置視圖窗口
              GLES30.glViewport(0, 0, width, height);
          }
      
          @Override
          public void onDrawFrame(GL10 gl) {
              mRunTime = System.currentTimeMillis() - mStartTime;
              //將顏色緩沖區(qū)設(shè)置為預(yù)設(shè)的顏色
              GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
              GLES30.glUniform1f(mTimeLocation, mRunTime / 1000f);
              //啟用頂點(diǎn)的數(shù)組句柄
              GLES30.glEnableVertexAttribArray(0);
              GLES30.glEnableVertexAttribArray(1);
              //準(zhǔn)備頂點(diǎn)坐標(biāo)和紋理坐標(biāo)
              GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);
              GLES30.glVertexAttribPointer(1, 2, GLES30.GL_FLOAT, false, 0, textureBuffer);
              //激活紋理
              GLES30.glActiveTexture(GLES30.GL_TEXTURE);
              //綁定紋理
              GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureId);
              //繪制貼圖
              GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, 4);
              //禁止頂點(diǎn)數(shù)組句柄
              GLES30.glDisableVertexAttribArray(0);
              GLES30.glDisableVertexAttribArray(1);
          }
      
          private void getFloatBuffer() {
              float[] vertex = new float[] {
                      1f, 1f, 0f,     //V0
                      -1f, 1f, 0f,    //V1
                      -1f, -1f, 0f,   //V2
                      1f, -1f, 0f     //V3
              };
              float[] texture = {
                      1f, 0f,     //V0
                      0f, 0f,     //V1
                      0f, 1.0f,   //V2
                      1f, 1.0f    //V3
              };
              vertexBuffer = mGLUtils.getFloatBuffer(vertex);
              textureBuffer = mGLUtils.getFloatBuffer(texture);
          }
      }
      

      ? MyGLUtils.java

      package com.zhyan8.glservice;
      
      import android.content.Context;
      import android.graphics.Bitmap;
      import android.graphics.BitmapFactory;
      import android.opengl.GLES30;
      import android.opengl.GLUtils;
      import android.opengl.Matrix;
      import java.io.BufferedReader;
      import java.io.InputStream;
      import java.io.InputStreamReader;
      import java.nio.ByteBuffer;
      import java.nio.ByteOrder;
      import java.nio.FloatBuffer;
      
      public class MyGLUtils {
          private Context mContext;
          private Bitmap mBitmap;
      
          public MyGLUtils(Context context) {
              mContext = context;
          }
      
          public FloatBuffer getFloatBuffer(float[] floatArr) {
              FloatBuffer fb = ByteBuffer.allocateDirect(floatArr.length * Float.BYTES)
                      .order(ByteOrder.nativeOrder())
                      .asFloatBuffer();
              fb.put(floatArr);
              fb.position(0);
              return fb;
          }
      
          //通過代碼片段編譯著色器
          public int compileShader(int type, String shaderCode){
              int shader = GLES30.glCreateShader(type);
              GLES30.glShaderSource(shader, shaderCode);
              GLES30.glCompileShader(shader);
              return shader;
          }
      
          //通過外部資源編譯著色器
          public int compileShader(int type, int shaderId){
              String shaderCode = readShaderFromResource(shaderId);
              return compileShader(type, shaderCode);
          }
      
          //鏈接到著色器
          public int linkProgram(int vertexShaderId, int fragmentShaderId) {
              final int programId = GLES30.glCreateProgram();
              //將頂點(diǎn)著色器加入到程序
              GLES30.glAttachShader(programId, vertexShaderId);
              //將片元著色器加入到程序
              GLES30.glAttachShader(programId, fragmentShaderId);
              //鏈接著色器程序
              GLES30.glLinkProgram(programId);
              return programId;
          }
      
          //從shader文件讀出字符串
          private String readShaderFromResource(int shaderId) {
              InputStream is = mContext.getResources().openRawResource(shaderId);
              BufferedReader br = new BufferedReader(new InputStreamReader(is));
              String line;
              StringBuilder sb = new StringBuilder();
              try {
                  while ((line = br.readLine()) != null) {
                      sb.append(line);
                      sb.append("\n");
                  }
                  br.close();
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return sb.toString();
          }
      
          //加載紋理貼圖
          public int loadTexture(int resourceId) {
              BitmapFactory.Options options = new BitmapFactory.Options();
              options.inScaled = false;
              mBitmap = BitmapFactory.decodeResource(mContext.getResources(), resourceId, options);
              final int[] textureIds = new int[1];
              // 生成紋理id
              GLES30.glGenTextures(1, textureIds, 0);
              // 綁定紋理到OpenGL
              GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIds[0]);
              GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR_MIPMAP_LINEAR);
              GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
              // 加載bitmap到紋理中
              GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, mBitmap, 0);
              // 生成MIP貼圖
              GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);
              // 取消綁定紋理
              GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
              return textureIds[0];
          }
      }
      

      ? vertex_shader.glsl

      attribute vec4 aPosition;
      attribute vec2 aTextureCoord;
      varying vec2 vTexCoord;
      
      void main() {
           gl_Position = aPosition;
           vTexCoord = aTextureCoord;
      }
      

      ? fragment_shader.glsl

      precision mediump float;
      uniform sampler2D uTextureUnit;
      varying vec2 vTexCoord;
      uniform float u_time;
      
      void main() {
           vec3 color = texture2D(uTextureUnit, vTexCoord).rgb;
           color.x += sin(u_time * 1.3 + 0.4) * 0.2;
           color.y += cos(u_time * 1.7 + 7.1) * 0.2;
           color.z += (sin(u_time) + cos(u_time)) * 0.2;
           gl_FragColor = vec4(color, 1.0);
      }
      

      ? 運(yùn)行效果如下。

      img

      ? 聲明:本文轉(zhuǎn)自【Android】基于SurfaceControlViewHost實(shí)現(xiàn)跨進(jìn)程渲染

      posted @ 2025-10-05 11:27  little_fat_sheep  閱讀(85)  評論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 无码精品人妻一区二区三区中| 国产资源精品中文字幕| 镇赉县| 色诱视频在线观看| 无套内谢少妇一二三四| 沙坪坝区| 国产激情国产精品久久源| 国产精品国产三级国产专| 国产精品美女自慰喷水| 99久久久国产精品免费无卡顿 | 国产亚洲精品合集久久久久| 亚洲欧洲一区二区天堂久久| 香蕉乱码成人久久天堂爱| 亚洲一区二区三区在线观看精品中文 | 国产精品制服丝袜第一页| 亚洲大老师中文字幕久热| 99re视频在线| 欧美成人精品三级在线观看| 国产精品亚洲综合久久小说| 国产欧美丝袜在线二区| 泊头市| 久久精产国品一二三产品| 熟女系列丰满熟妇AV| 激情综合色区网激情五月| 午夜福利精品一区二区三区| 2022亚洲男人天堂| 福利一区二区1000| 在线观看人成视频免费| 人妻人人妻a乱人伦青椒视频 | 日本免费一区二区三区日本| 风流少妇树林打野战视频| 亚洲人成网线在线播放VA| 国产永久免费高清在线观看| 日韩A人毛片精品无人区乱码| 奇米四色7777中文字幕| 无码一区二区三区久久精品| 国产久免费热视频在线观看| 久久av无码精品人妻系列试探| 国产口爆吞精在线视频2020版| 日韩精品福利一二三专区| 西西大胆午夜人体视频|