[RESOLVIDO] Reflection em Android

Em javaSE tenho esse código:

// invocar um método de uma classe a partir da String do seu nome
        String stringNomeClasse = "reflexao.Matematica";
        
        // carrega a classe
        Class classeGenerica = Class.forName(stringNomeClasse);

E funciona normal. Achei estranho que até por engano a package é Reflexao com R maiusculo e mesmo assim ele achou e não deu erro.

Daí tentei o mesmo código com Android

E ele dá ClassNotFoundException.

Mesmo mudando para package especifica, ou sem package, ele não reconhece a existência da classe.

Alguém tem alguma idéia a mais?

[quote=JoaoBluSCBR]Em javaSE tenho esse código:

// invocar um método de uma classe a partir da String do seu nome
        String stringNomeClasse = "reflexao.Matematica";
        
        // carrega a classe
        Class classeGenerica = Class.forName(stringNomeClasse);

E funciona normal. Achei estranho que até por engano a package é Reflexao com R maiusculo e mesmo assim ele achou e não deu erro.

Daí tentei o mesmo código com Android

E ele dá ClassNotFoundException.

Mesmo mudando para package especifica, ou sem package, ele não reconhece a existência da classe.

Alguém tem alguma idéia a mais?[/quote]

Reflection funciona normalmente no Android, inclusive, no AndOrm, uso muito reflection.

Poste sua estrutura de classes e seu código.

Não tenho nenhuma estrutura grande, apenas estou começando,

então peguei um exemplo na net e rodei em JavaSE, funcionou, depois
peguei o mesmo exemplo e adaptei ele dentro de uma Activity
para ver se rodava e na primeira chamada dá um NotFoundException.

Mas, está aí, o código do exemplo, se puder dar uma olhada e me ajudar;

E como anexo a imagem da estrutura do Eclipse

[code]
package br.com.Reflexao;

public class Matematica {

public double pi(){
    return Math.PI;
}

public static String nomeClasse(){
    return "Matemática";
}

public int soma(int a, int b){
    return a+b;
}

}[/code]

package br.com.Reflexao;

import android.app.Activity;
import android.os.Bundle;
import android.widget.*;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main extends Activity {
	
	private String array[] = new String[500];
	private int conta = 0;
	
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);               
        
        ListView out = (ListView) findViewById(R.id.list);
        
        for(int i=0; i<500; i++)
        	array[i] = "";    

        // invocar um método de uma classe a partir da String do seu nome
        String stringNomeClasse = "Matematica";
        String stringNomeMetodo = "pi";
        String stringNomeMetodoNome = "nomeClasse";
        String stringNomeSoma = "soma";

        try{
        	// carrega a classe
        	array[conta++] = "passo 1";
        	Class classeGenerica = Class.forName(stringNomeClasse);

        	// instancia um objeto
        	array[conta++] = "passo 2";
        	Object obj = classeGenerica.newInstance();

        	// retorna todos os métodos da classe passada
        	array[conta++] = "passo 3";
        	Method metodoPI = classeGenerica.getMethod(stringNomeMetodo);
        	array[conta++] = "passo 4";
        	Method metodoNome = classeGenerica.getMethod(stringNomeMetodoNome);

        	// invoda o método do obj instanciado
        	array[conta++] = "passo 5";
        	array[conta++] = metodoPI.invoke(obj).toString();

        	// caso o método seja estático
        	array[conta++] = "passo 6";
        	array[conta++] = (String)metodoNome.invoke(stringNomeClasse);

        	// chama um método com parâmetros
        	array[conta++] = "passo 7";
        	Method soma = classeGenerica.getMethod(stringNomeSoma, int.class, int.class);
        	array[conta++] = "passo 8";
        	array[conta++] = (String)soma.invoke(obj,5,10);
        }
        catch(ClassNotFoundException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        catch(IllegalAccessException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        catch(InstantiationException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        catch(NoSuchMethodException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        catch(InvocationTargetException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        
        String novo[] = new String[conta];
        for(int i=0; i<conta; i++)
        	novo[i] = array[i];
        
        out.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1 , novo));

    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello" android:id="@+id/mostra"/>
<ListView android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/list"></ListView>
</LinearLayout>


Se eu rodo um código genérico tipo:

String str = new String("Carro");
        Field atributos[] = null;
        Method metodos[] = null;

        Class c = str.getClass();

        atributos = c.getDeclaredFields();

        array[conta++] = "ATRIBUTOS:";
        
        for(int i=0; i < atributos.length; i++){
            array[conta++] = atributos[i].toString();
        }

        metodos = c.getMethods();
        array[conta++] = "MÉTODOS:";
        
        for(int i=0; i < metodos.length; i++){
        	array[conta++] = metodos[i].toString();
        }

Funciona perfeitamente, ele encontra os métodos e atributos. E os coloca no meu array e depois aparecem na lista.

O problema é apenas a minha classe que ele não encontra. E ela está na mesma package.

[quote=JoaoBluSCBR]Não tenho nenhuma estrutura grande, apenas estou começando,

então peguei um exemplo na net e rodei em JavaSE, funcionou, depois
peguei o mesmo exemplo e adaptei ele dentro de uma Activity
para ver se rodava e na primeira chamada dá um NotFoundException.

Mas, está aí, o código do exemplo, se puder dar uma olhada e me ajudar;

E como anexo a imagem da estrutura do Eclipse

[code]
package br.com.Reflexao;

public class Matematica {

public double pi(){
    return Math.PI;
}

public static String nomeClasse(){
    return "Matemática";
}

public int soma(int a, int b){
    return a+b;
}

}[/code]

package br.com.Reflexao;

import android.app.Activity;
import android.os.Bundle;
import android.widget.*;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main extends Activity {
	
	private String array[] = new String[500];
	private int conta = 0;
	
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);               
        
        ListView out = (ListView) findViewById(R.id.list);
        
        for(int i=0; i<500; i++)
        	array[i] = "";    

        // invocar um método de uma classe a partir da String do seu nome
        String stringNomeClasse = "Matematica";
        String stringNomeMetodo = "pi";
        String stringNomeMetodoNome = "nomeClasse";
        String stringNomeSoma = "soma";

        try{
        	// carrega a classe
        	array[conta++] = "passo 1";
        	Class classeGenerica = Class.forName(stringNomeClasse);

        	// instancia um objeto
        	array[conta++] = "passo 2";
        	Object obj = classeGenerica.newInstance();

        	// retorna todos os métodos da classe passada
        	array[conta++] = "passo 3";
        	Method metodoPI = classeGenerica.getMethod(stringNomeMetodo);
        	array[conta++] = "passo 4";
        	Method metodoNome = classeGenerica.getMethod(stringNomeMetodoNome);

        	// invoda o método do obj instanciado
        	array[conta++] = "passo 5";
        	array[conta++] = metodoPI.invoke(obj).toString();

        	// caso o método seja estático
        	array[conta++] = "passo 6";
        	array[conta++] = (String)metodoNome.invoke(stringNomeClasse);

        	// chama um método com parâmetros
        	array[conta++] = "passo 7";
        	Method soma = classeGenerica.getMethod(stringNomeSoma, int.class, int.class);
        	array[conta++] = "passo 8";
        	array[conta++] = (String)soma.invoke(obj,5,10);
        }
        catch(ClassNotFoundException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        catch(IllegalAccessException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        catch(InstantiationException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        catch(NoSuchMethodException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        catch(InvocationTargetException ex){
        	ex.printStackTrace();
        	array[conta++] = ex.toString();
        }
        
        String novo[] = new String[conta];
        for(int i=0; i<conta; i++)
        	novo[i] = array[i];
        
        out.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1 , novo));

    }
}

[code]

<?xml version="1.0" encoding="utf-8"?>





[/code][/quote]

Mas o nome da sua classe é

br.com.Reflexao.Matematica

e não apenas

Matematica

Sim, só que se eu colocar br.com.Reflexao.Matematica

dá aquele erro de Force Close.

Nem roda até o passo 1.

Estranho não? Por que uma diferença de String produziria um force close.

Ou chega, passa e dá erro em outro ponto.

Mas daí não tenho como identificar onde.

Ainda não me entendi com o Debug do Android no Eclipse.

Nada como outra pessoa para fazer a gente pensar se não está fazendo algo errado.

Sim, a classe é br.com.Reflexao.Matematica

Daí dá um force Close, mas é óbvio que tinha que ver onde.

E dá no último Invoke por que estou usando um Casting nada a ver.

Então isso está resolvido.

Agora, se puder me dizer uma coisa, já que você usa reflection:

Se eu criasse e compilasse uma classe, uma externa, que não está no meu projeto, como
a minha matemática. Como eu a colocaria num “jar” Android???

Não sei se estou querendo demais. Minha idéia é criar um projeto Android, fixo, e
colocar classes conhecidas para o sistema incorporar elas. Isso é possível, ou todas
as classes tem que estar no Manifest???

Obrigado por enquanto.

[quote=JoaoBluSCBR]Nada como outra pessoa para fazer a gente pensar se não está fazendo algo errado.

Sim, a classe é br.com.Reflexao.Matematica

Daí dá um force Close, mas é óbvio que tinha que ver onde.

E dá no último Invoke por que estou usando um Casting nada a ver.

Então isso está resolvido.

Agora, se puder me dizer uma coisa, já que você usa reflection:

Se eu criasse e compilasse uma classe, uma externa, que não está no meu projeto, como
a minha matemática. Como eu a colocaria num “jar” Android???

Não sei se estou querendo demais. Minha idéia é criar um projeto Android, fixo, e
colocar classes conhecidas para o sistema incorporar elas. Isso é possível, ou todas
as classes tem que estar no Manifest???

Obrigado por enquanto.[/quote]

Vc poderia ter essas classes externas todas num jar, e importar esse jar no seu projeto.