Programação com OpenGL/Instalação/Android NDK: diferenças entre revisões

[edição não verificada][edição não verificada]
Conteúdo apagado Conteúdo adicionado
Linha 178:
 
== Carregamento da biblioteca nativa indisponível ==
 
Se aparecer este erro:
E/AndroidRuntime( 3021): java.lang.RuntimeException: Unable to start activity
ComponentInfo{org.wikibooks.OpenGL/android.app.NativeActivity}: java.lang.IllegalArgumentException:
Unable to load native library: /data/data/org.wikibook.OpenGL/lib/libnative-activity.so
O sistema não pode carregar sua .so para acessar ao baixo nível do sistema.
 
Para obter maiores informações você precisa criar um aplicativo Java bem simples para carregar as bibliotecas manualmente:
<source lang="java">
package com.example.helloandroid;
 
import android.app.Activity;
import android.os.Bundle;
 
public class HelloAndroid extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.loadLibrary("native-activity");
}
}
</source>
 
Pode aparecer um este erro mais especifico, existe uma falha na implementação do STL:
E/AndroidRuntime(3009): java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1311]:
2323 cannot locate '_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc'...
ou falta uma dependência:
E/AndroidRuntime( 3327): java.lang.UnsatisfiedLinkError: Cannot load library:link_image[1962]:
2323 could not load needed library 'libglut.so.3' for 'libnative-activity.so'
(load_library[1104]: Library 'libglut.so.3' not found)
 
No pior caso, a biblioteca pode não carregar totalmente.
Isto pode acontecer caso quando o construtor do C++ de uma global estática quebrar enquanto chama a biblioteca, mesmo antes de sua aplicação ser iniciada.
Você precisa reproduzir um carregamento de uma biblioteca em C básico:
<source lang="c">
#include <stdio.h>
#include <dlfcn.h>
 
int main(int argc, char* argv[]) {
const char* err = NULL;
char* filename = "/data/data/org.wikibooks.OpenGL/lib/libnative-activity.so";
 
if (argc == 2)
filename = argv[1];
 
printf("Clearing errors: "); fflush(stdout);
err = dlerror();
printf("%s\n", (err == NULL) ? "OK" : err); fflush(stdout);
 
printf("Loading library: "); fflush(stdout);
void* handle = dlopen(filename, RTLD_LAZY);
err = dlerror();
printf("%s\n", (err == NULL) ? "OK" : err); fflush(stdout);
if (handle != NULL) {
printf("Loading symbol: "); fflush(stdout);
dlsym(handle, "ANativeActivity_onCreate");
err = dlerror();
printf("%s\n", (err == NULL) ? "OK" : err); fflush(stdout);
}
}
</source>
 
Para manda-lo para o dispositivo execute isto:
<source lang="bash">
$ arm-linux-androideabi-gcc test-dlsym.c
$ adb push a.out /
$ adb shell
# /a.out
Clearing errors: OK
Loading library: OK
Loading symbol: OK
</source>
Você também pode usar o <code>strace</code> que é mais precisa:
<source lang="bash">
# strace /a.out
</source>
 
Lá não possui um <code>ldd</code> como padrão do Android, mas você pode simular ele usando:
<source lang="bash">
arm-linux-androideabi-objdump -x libs/armeabi/libnative-activity.so | grep NEEDED
# ou
arm-linux-androideabi-readelf -d libs/armeabi/libnative-activity.so | grep NEEDED
</source>
 
== Referências ==