0

我正在创建一个使用 api 发送短信的 android 应用程序。当我尝试取消异步任务并开始另一个任务时,我面临强制关闭问题。我想要做的是,如果消息没有在 5 秒内发送,进度对话框应该消失,异步任务应该被取消,新任务应该开始。我为此编写了一个代码。请帮我解决错误。

09-18 10:55:40.456: E/AndroidRuntime(3273): FATAL EXCEPTION: AsyncTask #1
09-18 10:55:40.456: E/AndroidRuntime(3273): java.lang.RuntimeException: An error   
occured while executing doInBackground()
09-18 10:55:40.456: E/AndroidRuntime(3273):     at   
android.os.AsyncTask$3.done(AsyncTask.java:200)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at 
java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at  
java.util.concurrent.FutureTask.setException(FutureTask.java:125)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at 
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at  
java.util.concurrent.FutureTask.run(FutureTask.java:138)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at java.lang.Thread.run(Thread.java:1019)
09-18 10:55:40.456: E/AndroidRuntime(3273): Caused by: java.lang.RuntimeException: Can't create 
handler inside thread that has not called Looper.prepare()
09-18 10:55:40.456: E/AndroidRuntime(3273):     at android.os.Handler.<init>(Handler.java:121)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at android.widget.Toast.<init>(Toast.java:68)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at android.widget.Toast.makeText(Toast.java:231)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at 
com.widgets.application.MainActivity$sendMessageAsync.doInBackground(MainActivity.java:260)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at 
com.widgets.application.MainActivity$sendMessageAsync.doInBackground(MainActivity.java:1)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at 
android.os.AsyncTask$2.call(AsyncTask.java:185)
09-18 10:55:40.456: E/AndroidRuntime(3273):     at 
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
09-18 10:55:40.456: E/AndroidRuntime(3273):     ... 4 more
09-18 10:55:43.432: E/WindowManager(3273): Activity com.widgets.application.MainActivity has leaked 
window com.android.internal.policy.impl.PhoneWindow$DecorView@40594188 that was originally added here
09-18 10:55:43.432: E/WindowManager(3273): android.view.WindowLeaked: Activity  
com.widgets.application.MainActivity has leaked window 
com.android.internal.policy.impl.PhoneWindow$DecorView@40594188 that was originally added here
09-18 10:55:43.432: E/WindowManager(3273):  at android.view.ViewRoot.<init>(ViewRoot.java:258)
09-18 10:55:43.432: E/WindowManager(3273):  at  
android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
09-18 10:55:43.432: E/WindowManager(3273):  at 
android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
09-18 10:55:43.432: E/WindowManager(3273):  at 
android.view.Window$LocalWindowManager.addView(Window.java:424)
09-18 10:55:43.432: E/WindowManager(3273):  at android.app.Dialog.show(Dialog.java:241)
09-18 10:55:43.432: E/WindowManager(3273):  at   
android.app.ProgressDialog.show(ProgressDialog.java:107)
09-18 10:55:43.432: E/WindowManager(3273):  at 
android.app.ProgressDialog.show(ProgressDialog.java:90)
09-18 10:55:43.432: E/WindowManager(3273):  at  
com.widgets.application.MainActivity.onClick(MainActivity.java:331)
09-18 10:55:43.432: E/WindowManager(3273):  at android.view.View.performClick(View.java:2485)
09-18 10:55:43.432: E/WindowManager(3273):  at android.view.View$PerformClick.run(View.java:9080)
09-18 10:55:43.432: E/WindowManager(3273):  at android.os.Handler.handleCallback(Handler.java:587)
09-18 10:55:43.432: E/WindowManager(3273):  at android.os.Handler.dispatchMessage(Handler.java:92)
09-18 10:55:43.432: E/WindowManager(3273):  at android.os.Looper.loop(Looper.java:123)
09-18 10:55:43.432: E/WindowManager(3273):  at  
android.app.ActivityThread.main(ActivityThread.java:3683)
09-18 10:55:43.432: E/WindowManager(3273):  at java.lang.reflect.Method.invokeNative(Native Method)
09-18 10:55:43.432: E/WindowManager(3273):  at java.lang.reflect.Method.invoke(Method.java:507)
09-18 10:55:43.432: E/WindowManager(3273):  at 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
09-18 10:55:43.432: E/WindowManager(3273):  at  
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
09-18 10:55:43.432: E/WindowManager(3273):  at dalvik.system.NativeStart.main(Native   Method)

代码

public class MainActivity extends Activity implements OnPanelListener, OnClickListener, OnItemClickListener {

final static int RQS_PICK_CONTACT = 1;
public static String sendSmsToNumber = "";

private EditText editText, editUserName, editPassword;
private ArrayList<Map<String, String>> mPeopleList;
private SimpleAdapter mAdapter;
private AutoCompleteTextView mTxtPhoneNo;
private Panel bottomPanel;
private Panel topPanel;
private Button btnsend;
private ProgressDialog pd;
//private String gateway_name;
private Spinner spinner1;
Context context;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    editUserName = (EditText) findViewById(R.id.editTextUserName);
    editPassword = (EditText) findViewById(R.id.editTextPassword);
    mTxtPhoneNo = (AutoCompleteTextView) findViewById(R.id.mmWhoNo);
    mTxtPhoneNo.setTextColor(Color.BLACK);
    editText = (EditText) findViewById(R.id.editTextMessage);
    spinner1 = (Spinner) findViewById(R.id.spinnerGateway);
    btnsend = (Button) findViewById(R.id.btnSend);
    btnsend.setOnClickListener(this);
    mPeopleList = new ArrayList<Map<String, String>>();
    PopulatePeopleList();
    mAdapter = new SimpleAdapter(this, mPeopleList, R.layout.custcontview,
            new String[] { "Name", "Phone", "Type" }, new int[] {
                    R.id.ccontName, R.id.ccontNo, R.id.ccontType });
    mTxtPhoneNo.setAdapter(mAdapter);
    mTxtPhoneNo.setOnItemClickListener(this);
    Button buttonPickContact = (Button) findViewById(R.id.btnContact);
    buttonPickContact.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View arg0) {
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
            startActivityForResult(intent, RQS_PICK_CONTACT);
        }
    });     
    init();
    Panel panel;
    topPanel = panel = (Panel) findViewById(R.id.mytopPanel);
    panel.setOnPanelListener(this);
    panel.setInterpolator(new BounceInterpolator(Type.OUT));

}

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data){
     super.onActivityResult(requestCode, resultCode, data);        
      if(requestCode == RQS_PICK_CONTACT){
          if(resultCode == RESULT_OK){
              Uri contactData = data.getData();
                Cursor cursor =  managedQuery(contactData, null, null, null, null);
                cursor.moveToFirst();
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                sendSmsToNumber = number;
                trimContactNumber();
                mTxtPhoneNo.setText(name + " <" + number + ">");
          }
      }
 }

public void trimContactNumber() {
    sendSmsToNumber = sendSmsToNumber.replace("-", "");
    sendSmsToNumber = sendSmsToNumber.replace("+91", "");
    if(sendSmsToNumber.length() > 10){
        sendSmsToNumber = sendSmsToNumber.substring(1, sendSmsToNumber.length());
    }
}

public void PopulatePeopleList() {
    mPeopleList.clear();
    Cursor people = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    while (people.moveToNext()) {
        String contactName = people.getString(people.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
        String contactId = people.getString(people.getColumnIndex(ContactsContract.Contacts._ID));
        String hasPhone = people.getString(people.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));

        if ((Integer.parseInt(hasPhone) > 0)) {
            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
            while (phones.moveToNext()) {
                String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                String numberType = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
                Map<String, String> NamePhoneType = new HashMap<String, String>();
                NamePhoneType.put("Name", contactName);
                NamePhoneType.put("Phone", phoneNumber);
                if (numberType.equals("0"))
                    NamePhoneType.put("Type", "Work");
                else if (numberType.equals("1"))
                    NamePhoneType.put("Type", "Home");
                else if (numberType.equals("2"))
                    NamePhoneType.put("Type", "Mobile");
                else
                    NamePhoneType.put("Type", "Other");
                mPeopleList.add(NamePhoneType);
            }
            phones.close();
        }
    }
    people.close();
    startManagingCursor(people);
}

public void onItemClick(AdapterView<?> av, View arg1, int index, long arg3) {
    @SuppressWarnings("unchecked")
    Map<String, String> map = (Map<String, String>) av.getItemAtPosition(index);
    String name = map.get("Name");
    String number = map.get("Phone");
    mTxtPhoneNo.setText(name + " <" + number + ">");
    sendSmsToNumber = number;
    trimContactNumber();

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

private void init() {
    editUserName = (EditText) findViewById(R.id.editTextUserName);
    editPassword = (EditText) findViewById(R.id.editTextPassword);
    readPerson();
}

public void reset(View view) {
    PreferenceConnector.getEditor(this).remove(PreferenceConnector.NAME).commit();
    PreferenceConnector.getEditor(this).remove(PreferenceConnector.SURNAME).commit();
    PreferenceConnector.getEditor(this).remove(PreferenceConnector.AGE).commit();
    readPerson();
}

private void readPerson() {
    editUserName.setText(PreferenceConnector.readString(this,
            PreferenceConnector.NAME, null));
    editPassword.setText(PreferenceConnector.readString(this,
            PreferenceConnector.SURNAME, null));
}

public void save(View view) {
    String userNameTxt = editUserName.getText().toString();
    String PasswdTxt = editPassword.getText().toString();

    if (userNameTxt != null)
        PreferenceConnector.writeString(this, PreferenceConnector.NAME,userNameTxt);
    if (PasswdTxt != null)
        PreferenceConnector.writeString(this, PreferenceConnector.SURNAME,PasswdTxt);

}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_T) {
        topPanel.setOpen(!topPanel.isOpen(), false);
        return false;
    }
    if (keyCode == KeyEvent.KEYCODE_B) {
        bottomPanel.setOpen(!bottomPanel.isOpen(), true);
        return false;
    }
    return super.onKeyDown(keyCode, event);
}

public void onPanelClosed(Panel panel) {
    String panelName = getResources().getResourceEntryName(panel.getId());
    Log.d("TestPanels", "Panel [" + panelName + "] closed");
}

public void onPanelOpened(Panel panel) {
    String panelName = getResources().getResourceEntryName(panel.getId());
    Log.d("TestPanels", "Panel [" + panelName + "] opened");
}

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnectedOrConnecting()) {
        return true;
    }
    return false;
}

public boolean isValid() {
    if (editUserName.getText().length() == 10 && editPassword.getText().length() != 0 && sendSmsToNumber.length() >= 10 && editText.getText().length() != 0) {
        return true;
    }
    return false;
}

private class sendMessageAsync extends AsyncTask<Void, Void, String>{
    String resultSet;

    @Override
    protected void onPreExecute(){
    }

    @Override
    protected String doInBackground(Void... arg0) {
        String usrname = editUserName.getText().toString();
        String usrPassword = editPassword.getText().toString();
        String number = sendSmsToNumber;
        String message = editText.getText().toString();
        String gateway_name = String.valueOf(spinner1.getSelectedItem());
        String gatewayToUse = gateway_name; 
        Log.i("Gateway", String.valueOf(spinner1.getSelectedItem()));
        String msgreciever = number;
        String testMessage = message;
        try{
            SmsSender.sendMessage(msgreciever, testMessage, usrname,usrPassword, gatewayToUse);
            resultSet = SmsSender.toastText;
            timerDelayRemoveDialog(5000, pd);               

        } catch(Exception ex){
            Toast.makeText(MainActivity.this,"Error",Toast.LENGTH_SHORT).show();
        }
        return resultSet;
    }

    @Override
    protected void onPostExecute(String result){
        //super.onPostExecute(result);
        pd.dismiss();
        Toast.makeText(MainActivity.this,resultSet,Toast.LENGTH_SHORT).show();
    }

}

public void timerDelayRemoveDialog(long time, final Dialog d){
    new Handler().postDelayed(new Runnable() {
        public void run() {
            sendMessageAsync sma = new sendMessageAsync();
            sma.cancel(true);
            d.dismiss();
            Toast.makeText(MainActivity.this,"Sending Failed. Using Backup Server. Please Wait..",Toast.LENGTH_SHORT).show();
            sendBackupMessageAsync sbma = new sendBackupMessageAsync();
            sbma.execute();
        }
    }, time); 
}

private class sendBackupMessageAsync extends AsyncTask<Void, Void, String>{
    String resultSet;

    @Override
    protected void onPreExecute(){
    }

    @Override
    protected String doInBackground(Void... arg0) {         
        String usrname = editUserName.getText().toString();
        String usrPassword = editPassword.getText().toString();
        String number = sendSmsToNumber;
        String message = editText.getText().toString();
        String gateway_name = String.valueOf(spinner1.getSelectedItem());
        String gatewayToUse = gateway_name; 
        Log.i("Gateway", String.valueOf(spinner1.getSelectedItem()));
        String msgreciever = number;
        String testMessage = message;
        try{
            BackupSender.sendMessage(msgreciever, testMessage, usrname,usrPassword, gatewayToUse);
            resultSet = BackupSender.toastText;
        } catch(Exception ex){
            Toast.makeText(MainActivity.this,"Error",Toast.LENGTH_SHORT).show();
        }
        return resultSet;
    }

    @Override
    protected void onPostExecute(String result){
        //super.onPostExecute(result);
        pd.dismiss();
        Toast.makeText(MainActivity.this,resultSet,Toast.LENGTH_SHORT).show();
    }

}

public void onClick(View v) {
    if (v == btnsend){
        if (!isOnline()){
            Toast.makeText(MainActivity.this,"No Internet Access..Cannot Send SMS",Toast.LENGTH_SHORT).show();
        } else if (!isValid()){
            Toast.makeText(MainActivity.this,"All fields are required. Try Again.",Toast.LENGTH_SHORT).show();
        } else {
            save(v);
            pd.setCancelable(true);
            pd = ProgressDialog.show(MainActivity.this, "Free Sms","Sending SMS. Please Wait", true); 
            sendMessageAsync sma = new sendMessageAsync();
            sma.execute();
        }
    }
}
}
4

3 回答 3

0

You have to implement a onPostExcute method in you asyncTask. This method should take care of the UI updates. For instance:

protected void onPostExecute(Object result) {
        if (pd != null)
            pd.cancel();

        if (result.equals("1")) {

            Toast.makeText(getApplicationContext(),
                    "The log file has been sent", Toast.LENGTH_LONG).show();

            Intent j = new Intent(SendLogDialog.this, MyClass.class);
            startActivity(j);
        }

        else if (result.equals("2")) {

            new ErrorDialog(getApplicationContext(), "File doesn't exist",
                    "The log file doesn't exist, can't send mail",
                    "Show Settings", 1);
        }

        else if (result.equals("3")) {
            new ErrorDialog(getApplicationContext(),
                    "Error sending log file",
                    "The log file could not be sent, please try again",
                    "Ok", 5);
        }

    }

This is an example on how I show the user if something went wrong in processing of date in the doInBackground method. Notice that the ErrorDialog is a class that I created. If you want to start a new Activity from the asyncTask simply make a new Intent and start the Activity from the onPostExecute

于 2012-09-20T08:34:41.897 回答
0

需要重构代码以实现取消操作。当你想取消有中断的异步任务时,你可以调用:

yourtask.cancel(true);

在您的 doInBackground 方法中,您需要通过调用isCancelled ()来检查它是否被取消,以便尽快停止。取消操作后,它不会在您的异步任务中调用onPostExecute方法。

如果要指定超时,则不应将其放在doInBackground方法中。您想调用异步方法,然后调用第二个超时方法来取消之前的调用。

final MessageAsyncTask yourtask = new MessageAsyncTask();
yourtask.execute();
yourTimerDelayActiontoExecuteLater(5000, yourtask, d); // this will send cancel if finished flag is not set from async task 

您可以在异步任务中添加一个简单的构造函数,以不为不同的服务器名称创建另一个任务类。

于 2013-10-24T06:21:09.003 回答
0

引起:java.lang.RuntimeException:无法在未调用 Looper.prepare() 的线程内创建处理程序 09-18 10:55:40.456: E/AndroidRuntime(3273): at android.os.Handler.(Handler .java:121) 09-18 10:55:40.456: E/AndroidRuntime(3273): 在 android.widget.Toast .(Toast.java:68) 09-18 10:55:40.456: E/AndroidRuntime(3273) : 在 android.widget。Toast.makeText (Toast.java:231) 09-18 10:55:40.456: E/AndroidRuntime(3273): 在 com.widgets.application.MainActivity$sendMessageAsync。doInBackground (MainActivity.java:260)

您在. _ doInBackground()doInBackground() 在非 UI 线程上运行,您不能在其中执行 UI 功能。

因此,与其在 doInBackGround() 中烘烤任何东西,不如在其中设置一个标志,当您来到 onPostExecute() 时,检查该标志的值并在必要时制作 Toast。

于 2012-09-20T08:20:39.600 回答