Search Unity

Native texture loading on Android

Discussion in 'Android' started by mihakinova, Feb 4, 2016.

  1. mihakinova

    mihakinova

    Joined:
    Jan 6, 2015
    Posts:
    85
    I'm trying to load a png file from my streaming assets and get a Texture2D object from it. I already have the iOS solution to the problem (from THIS post).

    Sa basically what I want is:
    1. Send a StreamingAssets folder path of an image to an Android Java class.
    2. Asynchronusly load the texture to memory with opengl.
    3. Return the pointer to Unity and create the Texture2D object.
    My current native code is:
    Code (CSharp):
    1.     public static int loadTexture(final String path)
    2.     {
    3.         final int[] textureHandle = new int[1];
    4.  
    5.         GLES20.glGenTextures(1, textureHandle, 0);
    6.  
    7.         if (textureHandle[0] != 0)
    8.         {
    9.             final BitmapFactory.Options options = new BitmapFactory.Options();
    10.             options.inScaled = false;   // No pre-scaling
    11.  
    12.             // Read in the resource
    13.             final Bitmap bitmap = BitmapFactory.decodeFile(path, options);
    14.  
    15.             // Bind to the texture in OpenGL
    16.             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
    17.  
    18.             // Set filtering
    19.             GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
    20.             GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
    21.  
    22.             // Load the bitmap into the bound texture.
    23.             GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
    24.  
    25.             // Recycle the bitmap, since its data has been loaded into OpenGL.
    26.             bitmap.recycle();
    27.         }
    28.  
    29.         if (textureHandle[0] == 0)
    30.         {
    31.             throw new RuntimeException("Error loading texture.");
    32.         }
    33.  
    34.         return textureHandle[0];
    35.     }
    The path I send to this function is:
    Code (CSharp):
    1. Path.Combine(Application.streamingAssetsPath, "img.png");
    The problem I have is that the BitmapFactory.decodeFile can't find my file. But I checked and the img.png does get copied to the assets folder of the Android project.

    The error I get is:
    Does anyone have an idea why this is happening?
    I just want to get texture loading working for now, and I'll worry about the async part later on.
     
  2. callen

    callen

    Joined:
    Dec 31, 2013
    Posts:
    33
    I'm having a very similar issue, please let me know if you figure this out!

    I'm trying to load a wav file from StreamingAssets into the native android SoundPool class. My issue comes when I try to get the file data with this line:
    Code (CSharp):
    1. var filename = System.IO.Path.Combine(Application.streamingAssetsPath, filename) + ".wav";
    2. var fileDesc = UnityActivity.Call<AndroidJavaObject>("getAssets").Call<AndroidJavaObject>("openFd", filename);
    I have debugging output to show me the path, and it's very similar to yours:
    I verified the path by unzipping my apk file and sure enough I see an "assets/jump.wav" file inside. But for some reason android isn't seeing it.
     
  3. mihakinova

    mihakinova

    Joined:
    Jan 6, 2015
    Posts:
    85
    I did manage to solve that part of the problem, yes.
    The path that Application.streamingAssetsPath returns cant be used by native Java code as far as I can tell. The way I do it is I only pass the relative path of the file inside the StreamingAssets folder (e.g. "Sounds/mysound.wav") to the native function, and use Android's AssetManager to get the InputStream of the asset.

    This function receives the relative file name inside the assets folder an returns a Bitmap, but you can easily adapt it to anything you want:
    Code (CSharp):
    1.  private Bitmap getBitmapFromAsset(String filePath) {
    2.         AssetManager assetManager = activity.getAssets();
    3.  
    4.         InputStream istr;
    5.         Bitmap bitmap = null;
    6.         try {
    7.             istr = assetManager.open(filePath);
    8.             bitmap = BitmapFactory.decodeStream(istr);
    9.  
    10.             Matrix flip = new Matrix();
    11.             flip.postScale(1f, -1f);
    12.  
    13.             bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flip, true);
    14.         } catch (IOException e) {
    15.             // handle exception
    16.         }
    17.  
    18.         return bitmap;
    19.     }
     
  4. PeterGeneral

    PeterGeneral

    Joined:
    Jun 5, 2015
    Posts:
    14