0

APIを使用してSMSを送信するための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

原因:java.lang.RuntimeException:Looper.prepare()を呼び出していないスレッド内にハンドラーを作成できません09-18 10:55:40.456:E / AndroidRuntime(3273):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()に来たら、そのフラグの値を確認し、必要に応じてトーストを作成します。

于 2012-09-20T08:20:39.600 に答える
0

onPostExcuteasyncTaskにメソッドを実装する必要があります。このメソッドは、UIの更新を処理する必要があります。例えば:

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);
        }

    }

これは、メソッドの日付の処理で問題が発生した場合にユーザーに表示する方法の例doInBackgroundです。ErrorDialogは私が作成したクラスであることに注意してください。から新しいものを開始したい場合はActivityasyncTask単に新しいものを作成し、Intentからアクティビティを開始しますonPostExecute

于 2012-09-20T08:34:41.897 に答える
0

キャンセルアクションを実行するには、コードをリファクタリングする必要があります。中断して非同期タスクをキャンセルしたい場合は、次の電話をかけることができます。

yourtask.cancel(true);

doInBackgroundメソッド内で、isCancelled()を呼び出してできるだけ早く停止することにより、キャンセルされたかどうかを確認する必要があります。操作をキャンセルすると、非同期タスクでonPostExecuteメソッドは呼び出されません。

タイムアウトを指定する場合は、それをdoInBackgroundメソッド内に配置しないでください。非同期メソッドを呼び出してから、タイムアウトを使用して2番目のメソッドを呼び出し、前の呼び出しをキャンセルします。

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 に答える