我的Android应用程序中的运行时异常

时间:2013-06-03 08:19:33

标签: android

我正在尝试开发一个应用程序,该应用程序会生成对特定号码的未接来电。我的应用程序询问需要生成的手机号码和未接来电数量。我使用java本机代码来停止呼叫。代码如下

public void stopCall() throws RuntimeException
{
    try {
        //String serviceManagerName = "android.os.IServiceManager";
        String serviceManagerName = "android.os.ServiceManager";
        String serviceManagerNativeName = "android.os.ServiceManagerNative";
        String telephonyName = "com.android.internal.telephony.ITelephony";
        Class telephonyClass;
        Class telephonyStubClass;
        Class serviceManagerClass;
        Class serviceManagerStubClass;
        Class serviceManagerNativeClass;
        Class serviceManagerNativeStubClass;

        Method telephonyCall;
        Method telephonyEndCall;
        Method telephonyAnswerCall;
        Method getDefault;

        Method[] temps;
        Constructor[] serviceManagerConstructor;

        // Method getService;
        Object telephonyObject;
        Object serviceManagerObject;

        telephonyClass = Class.forName(telephonyName);
        telephonyStubClass = telephonyClass.getClasses()[0];
        serviceManagerClass = Class.forName(serviceManagerName);
        serviceManagerNativeClass = Class.forName(serviceManagerNativeName);

        Method getService = // getDefaults[29];
                serviceManagerClass.getMethod("getService", String.class);

        Method tempInterfaceMethod = serviceManagerNativeClass.getMethod(
                "asInterface", IBinder.class);

        Binder tmpBinder = new Binder();
        tmpBinder.attachInterface(null, "fake");

        serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder);
        IBinder retbinder = (IBinder)getService.invoke(serviceManagerObject,       "phone");
        Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class);

        telephonyObject = serviceMethod.invoke(null, retbinder);
        //telephonyCall = telephonyClass.getMethod("call", String.class);
        telephonyEndCall = telephonyClass.getMethod("endCall");
        //telephonyAnswerCall = telephonyClass.getMethod("answerRingingCall");

        telephonyEndCall.invoke(telephonyObject);



    } catch (Exception e) {
        e.printStackTrace();
        Log.e("dialing-example", "FATAL ERROR: could not connect to telephony subsystem",e);
       // Log.error(DialerActivity.this,
         //       "FATAL ERROR: could not connect to telephony subsystem");
        //Log.error(DialerActivity.this, "Exception object: " + e);
}
}

我还使用phonelistener重新启动我的应用程序,因为控件转到Dialer App。因此,为了运行它,我必须重新启动我的活动。

    private class PhoneCallListener extends PhoneStateListener {

    private boolean isPhoneCalling = false;

    String LOG_TAG = "LOGGING 123";

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {

        if (TelephonyManager.CALL_STATE_RINGING == state) {
            // phone ringing
            Log.i(LOG_TAG, "RINGING, number: " + incomingNumber);
        }

        if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
            // active
            isPhoneCalling = true;
            Log.i(LOG_TAG, "OFFHOOK");
            if(counter<(maxCounter-1))
            counter++;
            else
            {
                numberToDial="";
                counter=0;
                maxCounter=-1;
                save();
            //  Toast.makeText(getApplicationContext(),"Application Exiting "+counter, Toast.LENGTH_SHORT).show();
                System.exit(0);
                // restart app
                Intent i = getBaseContext().getPackageManager()
                    .getLaunchIntentForPackage(
                        getBaseContext().getPackageName());
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                startActivity(i);

            }

        }

        if (TelephonyManager.CALL_STATE_IDLE == state) {
            // run when class initial and phone call ended, 
            // need detect flag from CALL_STATE_OFFHOOK
            Log.i(LOG_TAG, "IDLE");

            if (isPhoneCalling) {
                isPhoneCalling = false;
                Log.i(LOG_TAG, "restart app");

                // restart app
                try{
                Intent i = getBaseContext().getPackageManager()
                          .getLaunchIntentForPackage(
                           getBaseContext().getPackageName());
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(i);
                }
                catch(RuntimeException ex)
                {
                    Log.i(LOG_TAG, "Exception caught"+ex.getMessage());
                }
                /*
                  Intent intent = new Intent(MainActivity.this, MainActivity.class);

                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);

                */

            /*  
                Intent intent = getBaseContext().getPackageManager()
                        .getLaunchIntentForPackage(
                            getBaseContext().getPackageName());

                intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

                startActivity(intent);
                */



            }

        }
    }

我使用OnResume函数来监控总计数。我使用shareReferences来存储总计数。如果总计数超过尝试次数,则应用程序退出。剩余代码如下。

    package com.example.dialerpro;
    import java.lang.reflect.Constructor;
    import java.lang.Process;
    import java.lang.reflect.Method;
    import java.sql.Date;
    import java.util.Calendar;
    import android.app.Activity;
    import android.content.ActivityNotFoundException;
    import android.content.Context;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.net.Uri;
    import android.os.Binder;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.telephony.PhoneStateListener;
    import android.telephony.TelephonyManager;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    import android.view.Menu;
    public class MainActivity extends Activity implements OnClickListener {
int maxCounter;
int counter=0;  
boolean resetFlag=false;
private String numberToDial="";
EditText txt_username;
Button okBtn;
Button resetBtn;
EditText txt_numberOfTries;
long currentDate;
long prevTime;
Date prevDate;
@Override
public void onCreate(Bundle savedInstanceState) {


    try{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    maxCounter=-1;
    okBtn=(Button)findViewById(R.id.okBtn);
    okBtn.setOnClickListener(this);

    resetBtn=(Button)findViewById(R.id.resetBtn);
    resetBtn.setOnClickListener(this);

    txt_username=(EditText)findViewById(R.id.txt_username);
    txt_username.setOnClickListener(this);

    txt_numberOfTries=(EditText)findViewById(R.id.txt_numberOfTries);
    txt_numberOfTries.setOnClickListener(this);
    // add PhoneStateListener
    PhoneCallListener phoneListener = new PhoneCallListener();
    TelephonyManager telephonyManager = (TelephonyManager) this
            .getSystemService(Context.TELEPHONY_SERVICE);
    telephonyManager.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);

    }
    catch(RuntimeException ex)
    {
        Log.i("From Create Method", "Run Time ");
    }

}

Intent callIntent=null;
public void launchDialer(String number){

     callIntent=null;
     try {
         String numberToDial = "tel:"+number;
            callIntent = new Intent(Intent.ACTION_CALL);
            callIntent.setData(Uri.parse(numberToDial));
            this.startActivity(callIntent); 
     }
     catch (ActivityNotFoundException activityException) {
            Log.e("dialing-example", "Call failed", activityException);
        } 
    catch (RuntimeException runException) {
         Log.e("dialing-example", "launch dialer Call failed 1",   runException);
     }

     try{

         Toast.makeText(getApplicationContext(), "Value "+counter, Toast.LENGTH_SHORT).show();
         Thread.sleep(4000);    
         //callIntent.

     }
      catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     catch (RuntimeException runException) {
         Log.e("dialing-example", "launch dialer Call failed 2", runException);
     }
       stopCall();
       try{
         Thread.sleep(2000);     
          }
           catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }

     }// stop call ends
boolean flagReset=false;
@Override
protected void onStart()
{
    super.onStart();

}
@Override
public void onPause() {
    super.onPause();
    if(counter > (maxCounter-1) )
    {
        numberToDial="";
        counter=0;
        maxCounter=-1;

    }
    save();
}
@Override
public void onDestroy()
{
    super.onDestroy();
/*  killApplicationProcess();
    try{
        Intent i = getBaseContext().getPackageManager()
                  .getLaunchIntentForPackage(
                   getBaseContext().getPackageName());
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(i);
        }
        catch(RuntimeException ex)
        {
            Log.i("aa", "Exception caught"+ex.getMessage());
        }

*/      
    Log.e("on destroy","On destroy");


}
private void killApplicationProcess()
{
android.os.Process.killProcess(android.os.Process.myPid());

}
@Override
public void onResume() {
    super.onResume();   
    try{
    //Toast.makeText(getApplicationContext(), "hi from resume", Toast.LENGTH_SHORT).show();
        //save();
       load();
       flagReset=false;
       long currentTime=System.currentTimeMillis();
       //double difference=(double)((currentTime-prevTime)/1000000);
     /*  try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
      */
    //   long currentTimeNow=System.currentTimeMillis();

       //double difference=(double)((currentTimeNow-currentTime));
       double difference=(double)((currentTime-prevTime));
      // Toast.makeText(getApplicationContext(), "hi from difference "+difference, Toast.LENGTH_LONG).show();
       if(difference> 10000) //10 seconds
       {
           Toast.makeText(getApplicationContext(), "hi from difference "+difference, Toast.LENGTH_SHORT).show();
           counter=0;
           numberToDial="";
           maxCounter=-1;
           save();

       }

       if(maxCounter==-1)
       {
           flagReset=true;
           counter=0;
           numberToDial="";  
       }
       if( (counter<=(maxCounter-1)) && flagReset==false )
       {            
        int ret=numberToDial.compareTo("");
            if(ret>0)
            {
            launchDialer(numberToDial);
            }
       }
    }
    catch(RuntimeException ex)
    {
        Log.i("From Resume", "Exception caught"+ex.getMessage());   
    }
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

private void save() {
    Date date=new Date(System.currentTimeMillis());
    SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString("numberToDial", numberToDial);
    editor.putInt("counter", counter);
    editor.putInt("maxCounter", maxCounter);
    long dte=System.currentTimeMillis();
    editor.putLong("time",dte);
    editor.putLong("date", date.getTime());
    editor.commit();
}

private void load() { 

    SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
    numberToDial=sharedPreferences.getString("numberToDial","");
    counter=sharedPreferences.getInt("counter",0);
    maxCounter=sharedPreferences.getInt("maxCounter",0);
    prevTime=0;
    prevTime=sharedPreferences.getLong("time",0);
    prevDate=new Date(sharedPreferences.getLong("date", 0));
    //Toast.makeText(getApplicationContext(), "Load "+prevTime, Toast.LENGTH_SHORT).show();
}
/**
 * @author robert.hinds
 *
 * Utility class for helper methods
 */


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}
// Launch the phone dialer
@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    switch (v.getId()) {
    case R.id.okBtn:
        numberToDial=txt_username.getText().toString();
        String tries=txt_numberOfTries.getText().toString();
        int ret=numberToDial.compareTo("");
        boolean flag=true;
        if(ret==0)
            {
            Toast.makeText(getApplicationContext(), "Please Enter the number "+numberToDial, Toast.LENGTH_LONG).show();
            flag=false;
            }
        ret=tries.compareTo("");
        if(ret==0)
        {   
            Toast.makeText(getApplicationContext(), "Please provide value for tries", Toast.LENGTH_LONG).show();
            flag=false;
        }
    else
    {
        maxCounter=Integer.parseInt(tries);
    }
        if(flag)
            {
            flagReset=false;
            launchDialer(numberToDial);
            }
    break;
    case R.id.resetBtn:
        flagReset=true;
        numberToDial="";
        txt_username.setText("");
        txt_numberOfTries.setText("");
        counter=0;
        save();
    break;
    case R.id.txt_username:
        numberToDial=txt_username.getText().toString();
        break;
    }
}
@Override
protected void onRestart() {
    // TODO Auto-generated method stub
    super.onRestart();
}

}

但是经过18次尝试后,我得到了以下运行时异常。

    06-03 11:32:54.611: D/AndroidRuntime(332): Shutting down VM
    06-03 11:32:54.611: W/dalvikvm(332): threadid=1: thread exiting with uncaught   exception (group=0x40015560)
    06-03 11:32:54.650: E/AndroidRuntime(332): FATAL EXCEPTION: main
    06-03 11:32:54.650: E/AndroidRuntime(332): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@405cbc90 is not valid; is your activity running?
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.view.ViewRoot.setView(ViewRoot.java:527)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.view.Window$LocalWindowManager.addView(Window.java:424)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2145)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1643)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.os.Handler.dispatchMessage(Handler.java:99)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.os.Looper.loop(Looper.java:123)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at android.app.ActivityThread.main(ActivityThread.java:3647)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at java.lang.reflect.Method.invokeNative(Native Method)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at java.lang.reflect.Method.invoke(Method.java:507)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
    06-03 11:32:54.650: E/AndroidRuntime(332):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    06-03 11:32:54.650: E/AndroidRuntime(332):  at dalvik.system.NativeStart.main(Native Method)
    06-03 11:32:55.951: D/dalvikvm(332): GC_CONCURRENT freed 491K, 48% free 3368K/6471K, external 1239K/1526K, paused 4ms+217ms
    06-03 11:32:59.350: I/Process(332): Sending signal. PID: 332 SIG: 9

我需要帮助才能找出此异常的原因。

0 个答案:

没有答案