如何在不同的线程上访问 android 应用程序的资产? (爪哇)

问题描述

这是我的问题的重新表述:How to access files form the Renderer class Opengles (android,java),但没有人回答,所以我决定换一种方式提问。

我正在为 android 构建一个 Opengl es 应用程序,我想访问一些本地文件。我的主要游戏循环位于 Renderer 类中,它是 GLSurfaceView.Renderer 的实现,将用于设置 MainActivity 中的视图。我知道获取某种本地文件*的唯一方法是执行 Activity.getAssets().open("file.something");但后来我需要 MainActivity。问题是,如果我正确理解我的研究,Renderer 类会自动在与 MainActivity 不同的线程上运行,从而导致 MainActivity.getAssets().open();什么都不回。如果那是解决方案,请帮助我找到解决方法或仅使用线程。

*我知道它们不被称为本地文件,但它们仍然用于处理您无法使用绝对路径 qnd 访问的文件,这正是我想要的。

编辑 #1:

这里是我调用 getAssets.open() 的地方:

import android.app.Activity;
import android.content.Context;
import android.opengl.GLES20;
import android.widget.Toast;
import com.GyooStudios.glu.MainActivity;
import com.GyooStudios.glu.ShaderProgram;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;


public abstract class ShaderProgram {
  
  private int programID;
  private int vertexShaderID;
  private int fragmentShaderID;
  
  public boolean hasFoundFile = true;
  public boolean isCompiled = true;
  public boolean canReadFile = true;
  
  public String exceptionError = "null";
  
  public ShaderProgram (MainActivity main,String vertexFile,String fragmentFile){
    vertexShaderID = loadShader(main,vertexFile,GLES20.GL_VERTEX_SHADER);
    fragmentShaderID = loadShader(main,fragmentFile,GLES20.GL_FRAGMENT_SHADER);
    
    programID = GLES20.glCreateProgram();
    GLES20.glAttachShader(programID,vertexShaderID);
    GLES20.glAttachShader(programID,fragmentShaderID);
    GLES20.glLinkProgram(programID);
    GLES20.glValidateProgram(programID);
  }
  
  public void start(){
    GLES20.gluseProgram(programID);
  }
  
  public void stop(){
    GLES20.gluseProgram(0);
  }
  
  protected abstract void bindAttributes();
  
  protected void bindAttribute(int attribute,String variableName){
    GLES20.glBindAttribLocation(programID,attribute,variableName);
  }
  
  private int loadShader(MainActivity main,String fileName,int type){
    int shaderID = 0;
    try{
      InputStream file = main.getAssets().open(fileName);
      Scanner scan = new Scanner(file);
      String code = new String();
      while(scan.hasNext()){
        code = new String(code + scan.nextLine() + "/n");
      }
      
      shaderID = GLES20.glCreateShader(type);
      GLES20.glShaderSource(shaderID,code);
      GLES20.glCompileShader(shaderID);
      int[] compileStatus = new int[1];
      GLES20.glGetShaderiv(shaderID,GLES20.GL_COMPILE_STATUS,compileStatus,0);
      if(compileStatus[0] == 0){
        Toast.makeText(main.getApplicationContext(),GLES20.glGetShaderInfoLog(shaderID),Toast.LENGTH_LONG);
        GLES20.glDeleteShader(shaderID);
        isCompiled = false;
      }
    }catch(FileNotFoundException e){
      hasFoundFile = false;
    }catch(IOException e){
      canReadFile = false;
    }catch(Exception e){
      isCompiled = false;
      exceptionError = "something went wrong";
      exceptionError = e.toString();
    }
    
    return shaderID;
    
  }
}

ShaderProgram 在这个类中实现:

import com.GyooStudios.glu.MainActivity;


public class StaticShader extends ShaderProgram{
  
  private static final String VERTEX_FILE = "quad.vertex";
  private static final String FRAGMENT_FILE = "quad.fragment";
  
  public StaticShader(MainActivity main){
    super(main,VERTEX_FILE,FRAGMENT_FILE);
    //bindAttributes();
  }
  
  @Override
  protected void bindAttributes(){
    super.bindAttribute(0,"position");
  }
  
}

StaticShader 用于在 Renederer 中创建的另一个类的构造函数中。这里正在使用渲染器,在 MainActivity 中:

import android.Manifest;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.widget.Toast;
import com.GyooStudios.glu.StaticShader;
import com.GyooStudios.glu.renderer;
import java.io.InputStream;
import java.util.Scanner;

public class MainActivity extends Activity {
    
    private renderer surface;
    private GLSurfaceView surfaceView;
    private int STORAGE_PERMISSION_CODE = 1;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //Keep in mind that renderer implements GLSurfaceView.Renderer
        //And yes,renderer class is with a lower case r,it's my mistake.
        super.onCreate(savedInstanceState);
        surfaceView = new GLSurfaceView(this);
        surfaceView.setEGLContextClientVersion(2);
        surface = new renderer(this);
        surfaceView.setRenderer(surface);
        setContentView(surfaceView);
    }
    
    protected void onPause(){
        super.onPause();
        surfaceView.onPause();
    }
    
    protected void onResume(){
        super.onResume();
        surfaceView.onResume();
    }

}

编辑#2: 我尝试只传递 Activity.getAssets(); 返回的 AssetManager;还有上下文。 AssetManager 允许应用程序运行,但它给了我一个异常,我无法确定是哪个。当我厌倦了使用 Toast.makeText(passedOnContext,exception.toString(),Toast.LENGTH_LONG);它使应用程序崩溃。 (是的,我使用 Toasts 来获取调试消息,这是我的 IDE 的限制,它没有在应用程序开发中提供终端)

解决方法

事实证明这根本不是问题!请参阅此处了解新问题:GLES20.glShaderSource does nothing