Using AdnRecordLoader class

Put your problem here if it does not fit any of the other categories.

Using AdnRecordLoader class

Postby Lassarin » Thu Nov 25, 2010 9:51 pm

Hi all
I'm trying to access SIM Records using Android. In particular I'm trying to use the class "AdnRecordLoader" which can read or write a generic EF SIM Record. This class isn't available in the public API provided by SDK, so I decided to use the "java reflection" in order to use it. This is the code...
Code: Select all
package com.example.simAdvancedTest;

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

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Message;
import android.widget.TextView;

public class MainActivity extends Activity {
   
    // GSM SIM file ids from TS 51.011
    static final int EF_ADN = 0x6F3A;
    static final int EF_FDN = 0x6F3B;
    static final int EF_SDN = 0x6F49;
    static final int EF_EXT1 = 0x6F4A;
    static final int EF_EXT2 = 0x6F4B;
    static final int EF_EXT3 = 0x6F4C;
    static final int EF_EXT6 = 0x6fc8;   // Ext record for EF[MBDN]
    static final int EF_MWIS = 0x6FCA;
    static final int EF_MBDN = 0x6fc7;
    static final int EF_PNN = 0x6fc5;
    static final int EF_SPN = 0x6F46;
    static final int EF_SMS = 0x6F3C;
    static final int EF_ICCID = 0x2fe2;
    static final int EF_AD = 0x6FAD;
    static final int EF_MBI = 0x6fc9;
    static final int EF_MSISDN = 0x6f40;
    static final int EF_SPDI = 0x6fcd;
    static final int EF_SST = 0x6f38;
    static final int EF_CFIS = 0x6FCB;
    static final int EF_IMG = 0x4f20;

    // USIM SIM file ids from TS 31.102
    public static final int EF_PBR = 0x4F30;

    // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
    static final int EF_MAILBOX_CPHS = 0x6F17;
    static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
    static final int EF_CFF_CPHS = 0x6F13;
    static final int EF_SPN_CPHS = 0x6f14;
    static final int EF_SPN_SHORT_CPHS = 0x6f18;
    static final int EF_INFO_CPHS = 0x6f16;
    static final int EF_CSP_CPHS = 0x6f15;

    // CDMA RUIM file ids from 3GPP2 C.S0023-0
    static final int EF_CST = 0x6f32;
    static final int EF_RUIM_SPN =0x6F41;

    // SMS record length from TS 51.011 10.5.3
    static public final int SMS_RECORD_LENGTH = 176;

    static final String MF_SIM = "3F00";
    static final String DF_TELECOM = "7F10";
    static final String DF_PHONEBOOK = "5F3A";
    static final String DF_GRAPHICS = "5F50";
    static final String DF_GSM = "7F20";
    static final String DF_CDMA = "7F25";
   
   
   /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
       
        try
         {
       
       super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
   
   
        TextView prova = (TextView) findViewById(R.id.view1);
       
        String stringaDiProva = "";
       
       
       
       
       
        try {
         
           
           // PRELEVO LE CLASSI CHE MI SERVONO
           
           Class phoneBase = Class.forName("com.android.internal.telephony.PhoneBase");

           Class gsmPhone = Class.forName("com.android.internal.telephony.gsm.GSMPhone");
           
           Class ADNManager = Class.forName("com.android.internal.telephony.AdnRecordLoader");
      
         Class defaultPhoneNotifier = Class.forName("com.android.internal.telephony.DefaultPhoneNotifier");
           
           Class phoneNotifier = Class.forName("com.android.internal.telephony.PhoneNotifier");
           
           Class commandsInterface = Class.forName("com.android.internal.telephony.CommandsInterface");
           
           Class RILCommands = Class.forName("com.android.internal.telephony.RIL");
         
         stringaDiProva += "Prima parte completata\n";
           
           //--------------------------------------
         
         try {
            
              Class[] typeParam = new Class[4];
              
              typeParam[0] = phoneNotifier;
              typeParam[1] = Context.class;
              typeParam[2] = commandsInterface;
              typeParam[3] = Boolean.class;
              

              Constructor RILCommandsCostructor = RILCommands.getConstructor(Context.class);
              
              Constructor[] defaultPhoneNotifierConstructors = defaultPhoneNotifier.getDeclaredConstructors();
              
              Constructor[] gsmBaseConstructors = gsmPhone.getDeclaredConstructors();
              
              Constructor ADNManagerConstructor = ADNManager.getConstructor(phoneBase);
         
            stringaDiProva += "Costruttore Inizializzato\n";
   
            try {
               
            // Prima vanno impostati i diritti di accesso
            defaultPhoneNotifierConstructors[0].setAccessible(true);
            
               
            Object defaultPhoneNotifierObject = defaultPhoneNotifierConstructors[0].newInstance();
               
            Object RILCommandsObject = RILCommandsCostructor.newInstance(this);
               
            
            Object[] param0 = new Object[3];
            param0[0] = this;
            param0[1] = RILCommandsObject;
            param0[2] = defaultPhoneNotifierObject;

            
            
            //----------------------------------------------------------------
            // Here I get an Unknown ERROR
   //----------------------------------------------------------------------------
      
            Object phoneObject = gsmBaseConstructors[0].newInstance(param0);
            
   //----------------------------------------------------------------------------         
            //----------------------------------------------------------------
            
            Object ADNObject =   ADNManagerConstructor.newInstance(phoneObject);
            
            stringaDiProva += "Seconda parte completata\n";
            
            
            
            typeParam[0] = Integer.class;
            typeParam[1] = Integer.class;
            typeParam[2] = Message.class;
            
            
            
            Method metodoADN = ADNManager.getMethod("loadAllFromEF", typeParam);
            
            stringaDiProva += "Terza parte completata\n";
            
            Message messaggio = new Message();
            
            Object[] param = new Object[3];
            
            param[0] = EF_MSISDN;
            param[1] = EF_EXT1;
            param[2] = messaggio;
            
            
            
            metodoADN.invoke(ADNObject, param);
            
            stringaDiProva += "Quarta parte completata\n";
            
            stringaDiProva += messaggio.toString();
            
            
            } catch (IllegalArgumentException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
               stringaDiProva += e + "\n";
            } catch (InstantiationException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
               stringaDiProva += e + "\n";
            } catch (IllegalAccessException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
               stringaDiProva += e + "\n";
            } catch (InvocationTargetException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
               stringaDiProva += e + "\n";
            }
   
         } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            stringaDiProva += e + "\n";
         } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            stringaDiProva += e + "\n";
         }
       
        } catch (ClassNotFoundException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
         stringaDiProva += e + "\n";
      }
       
       
       
       
       
       
       
       
        prova.setText(stringaDiProva);
       
         } catch (RuntimeException e) {
            
            e.printStackTrace();
            
            
         }
       
   
    }
}



In this project I'm trying to use reflection in order to get this equivalent code:
Code: Select all

DefaultPhoneNotifier phoneNot = new DefaultPhoneNotifier();

RIL rilcommands = new RIL(this);

GSMPhone gsmPhone = new GSMPhone(this, rilcommands, phoneNot);

new AdnRecordLoader(gsmPhone).loadAllFromEF(EF_MSISDN, EF_EXT1, messaggio);



The problem is that I get an EXCEPTION at the line "Object phoneObject = gsmBaseConstructors[0].newInstance(param0);". Oddly this exception is NOT "caught" by the app (even if all the code is surrounded by "try/catch"), so I cannot understand what problem is it.

The Manifest has these permissions:
android.permission.READ_PHONE_STATE
android.permission.READ_CONTACTS
android.permission.MODIFY_PHONE_STATE
android.permission.HARDWARE_TEST
android.permission.WRITE_PHONE_STATE
Lassarin
Freshman
Freshman
 
Posts: 5
Joined: Thu Nov 25, 2010 9:16 pm

Top

Re: Using AdnRecordLoader class

Postby Lassarin » Sun Nov 28, 2010 11:55 am

I changed the code in order to run the method "getDefaultPhone" in a Looper Thread, using the PhoneFactory in the internal package "com.android.internal.telephony"

Code: Select all
package com.example.simAdvancedTest;

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

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends Activity {
   
   
   // ------------ SIM FILES -------------------
   
   // GSM SIM file ids from TS 51.011
    static final int EF_ADN = 0x6F3A;
    static final int EF_FDN = 0x6F3B;
    static final int EF_SDN = 0x6F49;
    static final int EF_EXT1 = 0x6F4A;
    static final int EF_EXT2 = 0x6F4B;
    static final int EF_EXT3 = 0x6F4C;
    static final int EF_EXT6 = 0x6fc8;   // Ext record for EF[MBDN]
    static final int EF_MWIS = 0x6FCA;
    static final int EF_MBDN = 0x6fc7;
    static final int EF_PNN = 0x6fc5;
    static final int EF_SPN = 0x6F46;
    static final int EF_SMS = 0x6F3C;
    static final int EF_ICCID = 0x2fe2;
    static final int EF_AD = 0x6FAD;
    static final int EF_MBI = 0x6fc9;
    static final int EF_MSISDN = 0x6f40;
    static final int EF_SPDI = 0x6fcd;
    static final int EF_SST = 0x6f38;
    static final int EF_CFIS = 0x6FCB;
    static final int EF_IMG = 0x4f20;

    // USIM SIM file ids from TS 31.102
    public static final int EF_PBR = 0x4F30;

    // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
    static final int EF_MAILBOX_CPHS = 0x6F17;
    static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
    static final int EF_CFF_CPHS = 0x6F13;
    static final int EF_SPN_CPHS = 0x6f14;
    static final int EF_SPN_SHORT_CPHS = 0x6f18;
    static final int EF_INFO_CPHS = 0x6f16;
    static final int EF_CSP_CPHS = 0x6f15;

    // CDMA RUIM file ids from 3GPP2 C.S0023-0
    static final int EF_CST = 0x6f32;
    static final int EF_RUIM_SPN =0x6F41;

    // SMS record length from TS 51.011 10.5.3
    static public final int SMS_RECORD_LENGTH = 176;

    static final String MF_SIM = "3F00";
    static final String DF_TELECOM = "7F10";
    static final String DF_PHONEBOOK = "5F3A";
    static final String DF_GRAPHICS = "5F50";
    static final String DF_GSM = "7F20";
    static final String DF_CDMA = "7F25";
   
   // ----------------------------------------------------------------------
   
   // -------------------------- other variables ---------------------------
   
    String stringaDiProva;
   

   
    TextView prova;
   
    Class phoneBase;
   
    Object defaultPhone;
   
    Class adnRecordLoader;
   
    Object adnInstance;
   
    Class phoneFactory;
   
    Method phoneBuilder;
   
   Constructor adnConstructor;
   
   Method loadEF;
   
   workerThread threadLavoratore;
   
   boolean finished = false;
   
   int messaggiDaElaborare = 0;
   
   
   
   
   /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
       
       super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
   
        stringaDiProva = "";
       
        prova = (TextView) findViewById(R.id.view1);
       
       
        try {
         phoneBase = Class.forName("com.android.internal.telephony.PhoneBase");
         
         phoneFactory = Class.forName("com.android.internal.telephony.PhoneFactory");
         
         adnRecordLoader = Class.forName("com.android.internal.telephony.AdnRecordLoader");
         
         stringaDiProva += "Ricerca classi completata con successo\n";
      //---------------------------------------------------------------------------------------------
   
         
         Message risposta = Message.obtain();
         
         
         
         stringaDiProva += "Inizio Thread\n";
         
         
         startWork();
         

       
       
       
        } catch (ClassNotFoundException e) {
         // TODO Auto-generated catch block
         stringaDiProva += e + "\n";
           e.printStackTrace();
      }
   
    }

   
   public void startWork()
   
   {
      
     try {
      
      
      if (threadLavoratore == null)
         threadLavoratore = new workerThread();
      
      threadLavoratore.start();
      
      boolean running = true;
      
      while (running) {
      
      
      if (threadLavoratore.workerHandler == null) {

         try {
            Thread.sleep(400);
         } catch (InterruptedException ie) {
         }
         continue;
      
      }
      
      if (threadLavoratore != null && messaggiDaElaborare == 0)
      {
         
         messaggiDaElaborare++;
         
         Message risposta = threadLavoratore.workerHandler.obtainMessage();
         
         threadLavoratore.workerHandler.sendMessage(risposta);
         
         
         if (finished == false)
            
         {
         
         try {
            Thread.sleep(400);
         } catch (InterruptedException ie) {
         }
         continue;
         
         }
      
         running = false;
         
         threadLavoratore.stop();
         
         threadLavoratore = null;
      
      }
      
      
      
      
      
      }
      

      
   } catch (RuntimeException e) { prova.setText(e.toString()); }
      
      
      
   }
   

   
    public class workerThread extends Thread {
       
      public Handler workerHandler;
     
       
       public void run() {
         Looper.prepare();
         
         stringaDiProva += "Thread in esecuzione\n";
         
         try {
                  phoneBuilder = phoneFactory.getMethod("getDefaultPhone", null);
               
                  Log.i("PROGRESSO", "-------------------FASE 1 COMPLETATA---------------");
                  
                  
               
               } catch (SecurityException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
                  Log.e("-------ERRORE------", e.toString());
               } catch (NoSuchMethodException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
                  Log.e("-------ERRORE--------", e.toString());
               }
            
            

            
                  workerHandler = new Handler() {
                       public void handleMessage(Message msg) {

                          try {
                        
                             Log.i("PROGRESSO", "-------------------HANDLER IN ESECUZIONE---------------");    
                            
                            
                            
                           defaultPhone = phoneBuilder.invoke(null);
                     

                        adnConstructor = adnRecordLoader.getConstructor(phoneBase);
                        
                        
                        Log.i("PROGRESSO", "-------------------INIZIO FASE FINALE---------------");   
                  

                        adnInstance = adnConstructor.newInstance(defaultPhone);
                           
                           
                           
                           
                           Class[] paramType = new Class[3];
                           
                           paramType[0] = Integer.class;
                           paramType[1] = Integer.class;
                           paramType[2] = Message.class;
                        
                           
                           loadEF = adnRecordLoader.getMethod("loadAllFromEF", paramType);
                              
                        
                        Object[] param = new Object[3];
                        
                        param[0] = EF_MSISDN;
                        param[1] = EF_EXT1;
                        param[2] = msg;
                        
                        Log.i("AVVISO", "---------------FASE FINALE----------------");

                           loadEF.invoke(adnInstance, param);
                        

                        prova.setText("Fine: " + msg.obj.toString());
                        
                        finished = true;
                      
                          } catch (IllegalArgumentException e) {
                           // TODO Auto-generated catch block
                           e.printStackTrace();
                           Log.e("--ERRORE--", e.toString());
                           finished = true;   
                        } catch (IllegalAccessException e) {
                           // TODO Auto-generated catch block
                           e.printStackTrace();
                           Log.e("--ERRORE--", e.toString());
                           finished = true;                        
                           } catch (InvocationTargetException e) {

                              e.printStackTrace();
                              Log.e("--ERRORE--", e.getCause().toString());
                              finished = true;   
                              
                        } catch (SecurityException e) {
                           // TODO Auto-generated catch block
                           e.printStackTrace();
                           Log.e("--ERRORE--", e.toString());
                           finished = true;                        
                           } catch (NoSuchMethodException e) {

                        } catch (InstantiationException e) {
                           // TODO Auto-generated catch block
                           e.printStackTrace();
                           Log.e("--ERRORE--", e.toString());
                           finished = true;                              
                           } catch (RuntimeException e) {
                           
                              e.printStackTrace();
                              Log.e("--ERRORE--", e.toString());
                              finished = true;      }

                      
                      
                      
                       }
                   };


               //---------------------------------------------------------
                   Looper.loop();

      }
       
     }



}




However I get the same annoying error "getDefaultPhone must be called by a Looper Thread" :? . How is it possible considering that I'm calling it from workerThread which is a Looper Thread???
What should I do???

Thank you for replying
Lassarin
Freshman
Freshman
 
Posts: 5
Joined: Thu Nov 25, 2010 9:16 pm

Re: Using AdnRecordLoader class

Postby Lassarin » Wed Dec 01, 2010 7:17 pm

Ok, I changed the "getDefaultPhone" method into "getGsmPhone" and I've invoked before "getGsmPhone" the "makeDefaultPhone" method. Now I can create an Instance of GSMPhone.

However at the line...

loadEF = adnRecordLoader.getMethod("loadAllFromEF", paramType);


I get this RuntimeException:

Code: Select all
java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.provider.Telephony.SPN_STRINGS_UPDATED from pid=319, uid=10038


Can I do something?
Lassarin
Freshman
Freshman
 
Posts: 5
Joined: Thu Nov 25, 2010 9:16 pm

Re: Using AdnRecordLoader class

Postby Lassarin » Mon Dec 13, 2010 1:13 pm

I found that the SecurityException is thrown after the method "makeDefaultPhone()" is invoked (this method creates an instance of GsmPhone, which sends the Intent causing the Exception). So the question is: Is there a way to create an instance of the class GSMPhone in the SDK without getting these "permission errors"?
Lassarin
Freshman
Freshman
 
Posts: 5
Joined: Thu Nov 25, 2010 9:16 pm

Re: Using AdnRecordLoader class

Postby pflammertsma » Tue Jan 25, 2011 1:56 pm

I tried to reproduce this, and using your code, it bombs out on the RuntimeException just as you said. I noticed that a InvocationTargetException is thrown behind the screens on this line:
Code: Select all
getDefaultPhone.invoke(null);


The method does appear to be executed as the RuntimeException ("PhoneFactory.getDefaultPhone must be called from Looper thread") is identical to the one declared in the Android source (http://hi-android.info/src/com/android/ ... a.html#155).

Have you gotten any further? Any new ideas/approaches?
pflammertsma
Freshman
Freshman
 
Posts: 2
Joined: Tue Jan 25, 2011 1:40 pm

Top

Return to Other Coding-Problems

Who is online

Users browsing this forum: No registered users and 15 guests