2015-01-02 3 views
1

Я построил операцию отправки и получения SMS, и все работает нормально. Получающая часть просто загружает все мои тексты из моего приложения для обмена сообщениями Android в ListView. Это тоже работает. Проблема заключается в том, когда приходит новое текстовое сообщение, оно срабатывает немедленно. Даже если я нахожусь в другом приложении или на главном экране, у меня появляется всплывающее окно, в котором говорится, что мое приложение разбилось, и он постоянно перематывается каждый раз, когда приходит новое сообщение. Почему он сбой и как его исправить? ListView, который содержит сообщения, должен обновляться при поступлении нового сообщения. Я исправлял этот код вместе, так что, скорее всего, я что-то упустил. Кроме того, просто сосредоточьтесь на классе SMSReceiverSMSListFragment.java) и refreshSmsInbox()SMSMain.java), так как это места, где происходит загрузка в мой ListView. Кроме того, updateList() обновляет весь этот процесс, но только если в моем почтовом ящике есть уже существующие сообщения. Было бы неплохо, если бы обновление могло реально обновляться в режиме реального времени. Это возможно? Заранее спасибо.Сбой при приеме SMS-сообщений при появлении нового текстового сообщения - Android

В моем манифесте, вот мое связанное с ними разрешение:

<uses-permission android:name="android.permission.SEND_SMS" /> 
<uses-permission android:name="android.permission.WRITE_SMS" /> 
<uses-permission android:name="android.permission.READ_SMS" /> 
<uses-permission android:name="android.permission.RECEIVE_SMS" /> 

<receiver android:name=".SMSReceiver" 
      android:exported="true"> 
     <intent-filter android:priority="999"> 
      <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
     </intent-filter> 
</receiver> 

SMSMain.java

package org.azurespot.practiceapp.sms; 

import java.util.ArrayList; 

import org.azurespot.practiceapp.R; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.app.PendingIntent; 
import android.content.ActivityNotFoundException; 
import android.content.ContentResolver; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.database.Cursor; 
import android.net.Uri; 
import android.os.Bundle; 
import android.provider.ContactsContract; 
import android.provider.ContactsContract.CommonDataKinds.Phone; 
import android.speech.RecognizerIntent; 
import android.telephony.SmsManager; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.EditText; 
import android.widget.ListView; 
import android.widget.TextView; 
import android.widget.Toast; 


public class SMSMain extends Activity { 

    protected EditText etPhoneNumber; 
    protected static EditText etMessage; 
    protected View dialogView; 
    private static final int CONTACT_PICKER_RESULT = 1001; 
    AlertDialog dialog; 
    protected static final int RESULT_SPEECH = 1; 
    private static SMSMain smsMain; 
    ArrayList<String> smsMessagesList = new ArrayList<String>(); 
    ListView smsListView; 
    ArrayAdapter<String> arrayAdapter; 

    public static SMSMain instance() { 
     return smsMain; 
    } 

    @Override 
    public void onStart() { 
     super.onStart(); 
     smsMain = this; 
    } 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_smsmain); 

     // initialize ListView for displaying SMS messages 
     smsListView = (ListView) findViewById(R.id.messages_list); 
     arrayAdapter = new ArrayAdapter<String>(this, 
       android.R.layout.simple_list_item_1, smsMessagesList); 
     smsListView.setAdapter(arrayAdapter); 
     // long click on ListView item will delete message 
     smsListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 
      @Override 
      public boolean onItemLongClick(AdapterView<?> parent, View view, 
        int pos, long arg3) { 

       //removes item at position you long-click on 
       smsMessagesList.remove(pos);//where arg2 is position of item you click 
       arrayAdapter.notifyDataSetChanged(); 

       return true; 
      } 
     }); 


    } // end onCreate 


    public void readSMS(View v){ 

     refreshSmsInbox(); 
    } 

    // adds text messages to the ListView via the adapter 
    public void refreshSmsInbox() { 
     ContentResolver contentResolver = getContentResolver(); 
     Cursor smsInboxCursor = contentResolver.query(Uri.parse 
        ("content://sms/inbox"), null, null, null, null); 
     int indexBody = smsInboxCursor.getColumnIndex("body"); 
     int indexAddress = smsInboxCursor.getColumnIndex("address"); 
     if (indexBody < 0 || !smsInboxCursor.moveToFirst()) return; 
     arrayAdapter.clear(); 
     do { 
      String str = "SMS From: " + smsInboxCursor.getString(indexAddress) + 
        "\n" + smsInboxCursor.getString(indexBody) + "\n"; 
      arrayAdapter.add(str); 
     } while (smsInboxCursor.moveToNext()); 
    } 

    public void updateList(final String smsMessage) { 
     arrayAdapter.insert(smsMessage, 0); 
     arrayAdapter.notifyDataSetChanged(); 
    } 


    public void composeSMS(View v){ 

     // build your dialog box 
     AlertDialog.Builder builder = new AlertDialog.Builder(SMSMain.this); 
     // Get the layout inflater & inflate the box 
     final LayoutInflater inflater = SMSMain.this.getLayoutInflater(); 
     dialogView = inflater.inflate(R.layout.dialog_compose_sms, null); 
     builder.setView(dialogView); 
    // get phone number and message IDs 
     etPhoneNumber = (EditText)dialogView.findViewById(R.id.sms_phone); 
     etMessage = (EditText) dialogView.findViewById(R.id.sms_message); 
     builder.setTitle("Send an SMS"); 
     builder.setPositiveButton("Send", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int id) { 

       // Turns the entered phone number and message into String 
       String phoneNumber = etPhoneNumber.getText().toString().trim(); 
       String message = etMessage.getText().toString().trim(); 
       // error check to make sure there is input 
       if (phoneNumber.length() > 0 && message.length() > 0) 
        // sends the SMS 
        sendSMS(phoneNumber, message);     
       else 
        Toast.makeText(getBaseContext(), 
         "Please enter a phone number and message.", 
         Toast.LENGTH_SHORT).show(); 
      } 
     }); 
     builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int id) { 
       // User cancelled the dialog 
       dialog.cancel(); 
      } 
     }); 
     // put all your builders in one create command 
     dialog = builder.create(); 
     // show the dialog box 
     dialog.show(); 

    } 

    // clicked the microphone button to start speech to text 
    public void speechToText(View v) { 

     Intent intent = new Intent(
          RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 
     intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US"); 

     try { 
      startActivityForResult(intent, RESULT_SPEECH); 
      etMessage.setText(""); 
     } catch (ActivityNotFoundException a) { 
      Toast t = Toast.makeText(getApplicationContext(), 
        "Ooopps! Your device doesn't support Speech to Text", 
        Toast.LENGTH_SHORT); 
      t.show(); 
     } 

    } 

    // method for sending the SMS 
    private void sendSMS(String phoneNumber, String message) 
     {   
      PendingIntent pi = PendingIntent.getActivity(this, 0, 
            new Intent(this, SMSMain.class), 0);     
      SmsManager sms = SmsManager.getDefault(); 
      sms.sendTextMessage(phoneNumber, null, message, pi, null);   
     } 

    public void addContact(View v) { 

     // add a contact. using Android's ContactPicker 
     Intent i = new Intent(Intent.ACTION_PICK, 
       ContactsContract.CommonDataKinds.Phone.CONTENT_URI); 
     startActivityForResult(i, CONTACT_PICKER_RESULT); 

    } 

    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 

     if (requestCode == RESULT_SPEECH){ 
      // speech to text result 
      switch (requestCode) { 
       case RESULT_SPEECH: { 
        if (resultCode == RESULT_OK && null != data) { 

         ArrayList<String> text = data 
           .getStringArrayListExtra 
           (RecognizerIntent.EXTRA_RESULTS); 

         etMessage.setText(text.get(0)); 
        } 
        break; 
       } 
      } 
     } // end if 

     // picks a contact, puts into EditText 
     if (resultCode == RESULT_OK) { 
      switch (requestCode) { 
      case CONTACT_PICKER_RESULT: 
       Cursor cursor = null; 
       String phone = ""; 
       try{ 
        Uri result = data.getData(); 
        // get the contact id from the URI 
        String id = result.getLastPathSegment(); 

        // query for phone number 
        cursor = getContentResolver().query(
          ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
          null, 
          ContactsContract.CommonDataKinds.Phone._ID + "=?", 
          new String[]{id}, null); 

        int phoneIdx = cursor.getColumnIndex(Phone.DATA); 

        if (cursor.moveToFirst()) { 
         phone = cursor.getString(phoneIdx); 
        } 
       } catch (Exception e) { 
         System.out.println("Getting contact failed."); 
       } finally { 

        etPhoneNumber.setText(phone, TextView.BufferType.EDITABLE); 

        if (phone.length() == 0) { 
          Toast.makeText(this, "No phone number found for contact.", 
                   Toast.LENGTH_LONG).show(); 
        } 
        if (cursor != null){ 
          cursor.close(); 
        } 

       } // end finally 
       break; 
      } 
     }  
    } 
} 

SMSListFragment.java

package org.azurespot.practiceapp.sms; 

import org.azurespot.practiceapp.R; 

import android.app.ListFragment; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.database.Cursor; 
import android.net.Uri; 
import android.os.Bundle; 
import android.provider.ContactsContract; 
import android.provider.ContactsContract.PhoneLookup; 
import android.telephony.SmsMessage; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Toast; 

public class SMSListFragment extends ListFragment{ 

    public static View viewList; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 

     // Defines the XML file for the fragment 
     viewList = inflater.inflate(R.layout.sms_messages_fragment, 
                 container, false); 

     return viewList; 
    } 

    public class SMSReceiver extends BroadcastReceiver{ 

     @Override 
     public void onReceive(Context context, Intent intent) { 

      //---get the SMS message passed in--- 
      Bundle bundle = intent.getExtras();   
      SmsMessage[] messages = null; 
      String msgString = ""; 

      if (bundle != null) 
      { 
       //---retrieve the SMS message received--- 
       Object[] pdus = (Object[]) bundle.get("pdus"); 
       messages = new SmsMessage[pdus.length];    
       for (int i = 0; i < messages.length; i++){ 
        messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);     
        msgString += "SMS From: " + messages[i].getOriginatingAddress();      
        msgString += " :"; 
        msgString += messages[i].getMessageBody().toString(); 
        msgString += "\n"; 



       } 

       //---display the new SMS message--- 
       SMSMain smsMain = SMSMain.instance(); 
       smsMain.updateList(msgString); 
      } 
     } 

    } 

} 

Logcat

01-01 18:24:09.444: E/AndroidRuntime(13141): FATAL EXCEPTION: main 
01-01 18:24:09.444: E/AndroidRuntime(13141): Process: org.azurespot.practiceapp, PID: 13141 
01-01 18:24:09.444: E/AndroidRuntime(13141): java.lang.RuntimeException: Unable to instantiate receiver org.azurespot.practiceapp.SMSReceiver: java.lang.ClassNotFoundException: Didn't find class "org.azurespot.practiceapp.SMSReceiver" on path: DexPathList[[zip file "/data/app/org.azurespot.practiceapp-2.apk"],nativeLibraryDirectories=[/data/app-lib/org.azurespot.practiceapp-2, /vendor/lib, /system/lib]] 
01-01 18:24:09.444: E/AndroidRuntime(13141): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2608) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at android.app.ActivityThread.access$1800(ActivityThread.java:173) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1379) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at android.os.Handler.dispatchMessage(Handler.java:102) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at android.os.Looper.loop(Looper.java:136) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at android.app.ActivityThread.main(ActivityThread.java:5579) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at java.lang.reflect.Method.invokeNative(Native Method) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at java.lang.reflect.Method.invoke(Method.java:515) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at dalvik.system.NativeStart.main(Native Method) 
01-01 18:24:09.444: E/AndroidRuntime(13141): Caused by: java.lang.ClassNotFoundException: Didn't find class "org.azurespot.practiceapp.SMSReceiver" on path: DexPathList[[zip file "/data/app/org.azurespot.practiceapp-2.apk"],nativeLibraryDirectories=[/data/app-lib/org.azurespot.practiceapp-2, /vendor/lib, /system/lib]] 
01-01 18:24:09.444: E/AndroidRuntime(13141): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:67) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at java.lang.ClassLoader.loadClass(ClassLoader.java:497) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at java.lang.ClassLoader.loadClass(ClassLoader.java:457) 
01-01 18:24:09.444: E/AndroidRuntime(13141): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2603) 
01-01 18:24:09.444: E/AndroidRuntime(13141): ... 10 more 

ответ

1

Когда вы объявляете приемник в манифесте:

<receiver android:name=".SMSReceiver" 
     android:exported="true"> 
    <intent-filter android:priority="999"> 
     <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
    </intent-filter> 
</receiver> 

. в android:name=".SMSReceiver" будет расширена на ваше имя пакета. То, что вы написали в манифеста равнозначно

<receiver android:name="org.azurespot.practiceapp.SMSReceiver" 
     android:exported="true"> 
    <intent-filter android:priority="999"> 
     <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
    </intent-filter> 
</receiver> 

Обратите внимание, что этот путь не совпадает с именем класса SMSReceiver вы определяете внутри вашего SMSListFragment, который является то, что ошибка LogCat указывает.

Возможно, вы должны использовать в манифесте android:name=".sms.SMSListFragment.SMSReceiver". Вложенный класс SMSReceiver также может быть объявлен статическим для доступа таким образом.

+0

Спасибо, stkent, я понятия не имел, что нужно. Хотя я сделал это изменение, и он все еще дает мне эту ошибку с новым именем. Я тоже сделал «SMSReceiver». 'java.lang.RuntimeException: не удается создать экземпляр получателя org.azurespot.practiceapp.sms.SMSListFragment.SMSReceiver: java.lang.ClassNotFoundException: не нашел класс" org.azurespot.practiceapp.sms.SMSListFragment.SMSReceiver "... ' – Azurespot

+0

Ну, это странно, потому что' org.azurespot.practiceapp.sms.SMSListFragment.SMSReceiver' теперь выглядит как правильный путь. Ваш 'SMSListFragment' все еще находится в пакете' sms', правильно? – stkent

+0

С другой стороны, мой код обновления находится в 'SMSMain' ... хотя список обновляется просто отлично, но это просто обновление в реальном времени, которое он не может обработать, а затем он сбой. Я не знаю, связаны ли они, но 'SMSMain' не находится в манифесте, хотя это не приемник, поэтому, возможно, этого не должно быть. – Azurespot