1. Nimm jetzt an unserem Uhans - 3. ADVENT - Gewinnspiel teil - Alle Informationen findest Du hier!

Aktuelle CallLogs ausgeben

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von sem_thesis, 07.04.2011.

  1. sem_thesis, 07.04.2011 #1
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Hallo zusammen!


    Ich arbeite noch immer an meinem CallLog-Service, der aktiviert wird, sobald der Telefon-Zustand (Variable PHONE_STATE) verändert wird.

    Dazu habe ich die folgende Listener-Klasse implementiert:
    Code:
        //////// Private Class MyPhoneStateListener /////////
        
        private class MyPhoneStateListener extends PhoneStateListener {
            
    
            // This method is a Listener on the Phone State: Whenever it changes --> a new query is made to Call Logs
              
            public void onCallStateChanged(int state, String incomingNumber){
                  
                   Log.d(TAG, "STATE HAS CHANGED!");
                   
                  // Register New Phone Logs  
                  
                  switch(state){
                      case TelephonyManager.CALL_STATE_IDLE:
                          Log.d(TAG, "Phone is in idle state.");
                          CollectAndSaveLogs();
                          break;
                      case TelephonyManager.CALL_STATE_OFFHOOK:
                          Log.d(TAG, "Phone-User has initiated/accepted a call");
                          break;
                      case TelephonyManager.CALL_STATE_RINGING:
                        Log.d(TAG, "Phone-User has received a call");
                        break;
                  }
                  
                  
    
                  
              }
    
        }
        
        
        
            public void CollectAndSaveLogs()    {
                
                // Declare all values, which need to be logged
                
                String date = new String();
                String time = new String();        
                String name = new String();
                String phonenumber = new String();
                String duration = new String();
                String callclassification = new String();
                String d = new String();
                
                
                
              // Collect new Phone Logs //
              
              Cursor c = getContentResolver().query(
                           android.provider.CallLog.Calls.CONTENT_URI,
                           null,
                           null,
                           null,
                           null);
                
              c.moveToFirst();
              
               date = formatDate.format(new Date());
               time = formatTime.format(new Date());
                name = c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME));
                phonenumber = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));
                d = c.getString(c.getColumnIndex(CallLog.Calls.DURATION));
                duration = formatDuration(d);
                callclassification = c.getString(c.getColumnIndex(CallLog.Calls.TYPE));
          
                  Log.d(TAG, date);
                  Log.d(TAG, time);
                  Log.d(TAG, name);
                  Log.d(TAG, phonenumber);
                  Log.d(TAG, duration);
                  Log.d(TAG, callclassification);
                  
                  c.close();
                  
              // Write new Phone Logs in Database //
              
              db.open();
              db.insertCallLogs(date, time, name, phonenumber, duration, callclassification);
              db.close();
            
            }
    
    Sobald der Phone in den inaktiven IDLE Zustand gelangt, sollte die Funktion CollectAndSaveLogs()jedesmal NEU aufgerufen werden und die neuesten Daten aufsammeln und in die Datenbank schreiben.

    Beim Testen habe ich jedoch gemerkt, dass einfach der erste Call (name, nummer, calltype) gespeichert wird. Der Listener wird immer wieder aufgerufen, doch die Logs geben immer noch die alten Werte an.

    Was soll das? Muss ich den cursor weiterbewegen mit moveToNext()? Oder muss ich eine andere Sortiermethode für den Cursor wählen (ASC und DESC - hab's probiert, aber es hat trotzdem nicht funktioniert).

    PS: Code ist im Attachment
     

    Anhänge:

    Zuletzt bearbeitet: 07.04.2011
  2. maniac103, 07.04.2011 #2
    maniac103

    maniac103 Android-Lexikon

    Beiträge:
    1,237
    Erhaltene Danke:
    1,157
    Registriert seit:
    24.01.2011
    Warte nach dem State-Wechsel nach IDLE einfach etwas (ich benutze 5s als Wartezeit). Wenn der Benutzer auflegt, muss die Schreibe-Datensatz-in-Datenbank-Magie, die ja auch von einem PhoneStateListener getriggert wird, ja auch erstmal laufen.
     
  3. sem_thesis, 07.04.2011 #3
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Ok, guter Ansatz.
    Hab's mit dem Thread versucht.

    Code:
                  switch(state){
                      case TelephonyManager.CALL_STATE_IDLE:
                          Log.d(TAG, "Phone is in idle state.");
                    try {
                        Thread.sleep(5000);
                          CollectAndSaveLogs();                    
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                          break;
                      case TelephonyManager.CALL_STATE_OFFHOOK:
                          Log.d(TAG, "Phone-User has initiated/accepted a call");
                          break;
                      case TelephonyManager.CALL_STATE_RINGING:
                        Log.d(TAG, "Phone-User has received a call");
                        break;
                  }
    
    Geht aber immer noch nicht..
     
    Zuletzt bearbeitet: 07.04.2011
  4. maniac103, 08.04.2011 #4
    maniac103

    maniac103 Android-Lexikon

    Beiträge:
    1,237
    Erhaltene Danke:
    1,157
    Registriert seit:
    24.01.2011
    Ja klar, damit hast du ja auch nur den Thread, der die Notifications verteilt, aufgehalten, aber nicht dafür gesorgt, dass die Datenbankeinträge schon mal passieren können.

    Stichworte (du willst ja für deine Semesterarbeit auch noch was lernen :D ) sind AlarmManager und PendingIntent. Die eigentliche Arbeit (Datenbankabfrage, Eintragen der Daten in deine Datenbank) solltest du ohnehin mit einem (Intent-)Service abhandeln (in einem Receiver sollte man nix tun, was lange dauert), und diesen Service kannst du dann über den Intent aufrufen.
     
  5. sem_thesis, 08.04.2011 #5
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Hmm... ok ich hatte schon einen BroadcastReceiver, der den Sercice aktiviert, falls der User das so gewünscht hat.
    Dann muss ich also einen zweiten Receiver einabauen?

    Ok, ich hab's jetzt so gemacht:

    1) ServiceEnabler.java: Die Klasse, die den Service aktiviert, falls dies vom User so gewünscht ist.
    Code:
    public class ServiceEnabler extends BroadcastReceiver {
        
        private static final String TAG = ServiceEnabler.class.getSimpleName();
        boolean prefPhone = true;
        
        
        @Override
        public void onReceive(Context context, Intent intent) 
        {
                if (prefPhone) {
                      Log.d(TAG, "Service is activated!");
                      Intent p = new Intent();
                    p.setAction("com.example.mylog.PhoneServiceReceiver");
                    context.startService(p);
                }
        }
        
    }
    
    2) PhoneServiceReceiver.java: Dies ist die Service-Klasse welche einen Listener erstellt und danach implementiert. Der eigentliche PhoneService wird als PendingIntent mit dem Alarmmanger zur Zeit "SystemClock.elapsedRealtime() + sleep" aufgerufen.

    Code:
    public class PhoneServiceReceiver extends Service {
        
        // Log-Tag for debugging
        private static final String TAG = PhoneService.class.getSimpleName();
    
        // Create Telephony + Listener variables
        public TelephonyManager telephony;
        public MyPhoneServiceListener phoneListener;
        
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        
        @Override
        public void onCreate() {
            super.onCreate();
            
               // Put a Listener on the Phone-State
    
            telephony = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
            phoneListener = new MyPhoneServiceListener();
            telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
            
        }
        
        
        private class MyPhoneServiceListener extends PhoneStateListener {
    
    
    
        // This method is a Listener on the Phone State: Whenever it changes --> a new query is made to Call Logs
            
            public void onCallStateChanged(int state, String incomingNumber)    {
              
                Log.d(TAG, "STATE HAS CHANGED!");
               
                // Register New Phone Logs  
              
                switch(state){
                      case TelephonyManager.CALL_STATE_IDLE:
                          Log.d(TAG, "Phone is in idle state.");
                          
                          // Hier comes the actual Service-Functionality
                          
                          Intent pService = new Intent();
                        pService.setAction("com.example.mylog.PhoneService");
    
                          int sleep = 5000; // Waiting time before Log-database is accessed
                          int flags = 0;
                          
                          PendingIntent piSync = PendingIntent.getService(getBaseContext(), 0, pService, flags);
                          Log.i(TAG, "schedulePendingSync: " + piSync.toString());
                          AlarmManager alarm = (AlarmManager) getBaseContext().getSystemService(Activity.ALARM_SERVICE);
                          alarm.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + sleep, piSync);
    
                          // Endof Service-Functionality
    
                          
                          break;
                      case TelephonyManager.CALL_STATE_OFFHOOK:
                          Log.d(TAG, "Phone-User has initiated/accepted a call");
                          break;
                      case TelephonyManager.CALL_STATE_RINGING:
                          Log.d(TAG, "Phone-User has received a call");
                          break;
              }
               
          }
    
        }
        
    }
    
    3) PhoneService.java: Die eigentliche Service Klasse - liest Logs und schreibt sie in eine Datenbank (enthält 3 Formattierungsfunktionen für Zeit/Datum/Dauer/Typ)
    Code:
    public class PhoneService extends Service {
        
        private static final String TAG = PhoneService.class.getSimpleName();
        public DBAdapter db;
    
    
        
        // Specify formatting of data and time --> looks awesome :D
        SimpleDateFormat formatDate = new SimpleDateFormat("dd-MM-yyyy");
        SimpleDateFormat formatTime = new SimpleDateFormat("HH:mm:ss");
        
        
        // Specify formatting for duration --> looks even more awesome :D    
        public String formatDuration(String input) {
            
            long seconds = Long.parseLong(input);
            StringBuffer buf = new StringBuffer();
            Log.d(TAG, input);
    
            int h = (int) Math.floor(seconds / 3600);
            int m = (int) Math.floor((seconds - h * 3600) / 60);
            int s = (int) seconds - h - m;
    
            buf
                .append(String.format("%02d", h))
                .append(":")
                .append(String.format("%02d", m))
                .append(":")
                .append(String.format("%02d", s));
    
            return buf.toString();
        }    
        
        // Specify interpretation of Calltype
        public String callType(int t)    {
            
            if (t == 0)            return "Outgoing Call";
            else if (t == 1)    return "Incoming Call";
            else if (t == 2)    return "Missed Call";
            return null;
    
        }
        
        
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        
        @Override
        public void onCreate() {
            super.onCreate();
                
              // Create Database
            db = new DBAdapter(getApplicationContext());
            
            
            // Declare all values, which need to be logged
            
            String date = new String();
            String time = new String();        
            String name = new String();
            String phonenumber = new String();
            String duration = new String();
            String callclassification = new String();
            String d = new String();
            int e;
            
            
            
            // Collect new Phone Logs //
          
            Cursor c = getContentResolver().query(
                       android.provider.CallLog.Calls.CONTENT_URI,
                       null,
                       null,
                       null,
                       android.provider.CallLog.Calls.DATE + " ASC");
            
            c.moveToFirst();
          
            date = formatDate.format(new Date());
            time = formatTime.format(new Date());
                name = c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME));
                phonenumber = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));
                d = c.getString(c.getColumnIndex(CallLog.Calls.DURATION));
                duration = formatDuration(d);
                e = c.getColumnIndex(CallLog.Calls.TYPE);
                callclassification = callType(e);
      
              Log.d(TAG, date);
              Log.d(TAG, time);
              Log.d(TAG, name);
              Log.d(TAG, phonenumber);
              Log.d(TAG, duration);
              Log.d(TAG, callclassification);
              
              c.close();
              
              // Write new Phone Logs in Database //
          
              db.open();
              db.insertCallLogs(date, time, name, phonenumber, duration, callclassification);
              db.close();
    }
    }
    
    
    Oke... und Eclipse zeigt keine (Syntax-)Fehler an. Die App crasht bei einem Anruf sofort.
    Wo liegt der konzeptienelle Fehler?


    PS: Im AndroidManifest.xml habe ich PhoneServiceReceiver und PhoneService als Services und ServiceEnabler als Receiver eingetragen. Muss ich sonst was eintragen?
     

    Anhänge:

    Zuletzt bearbeitet: 08.04.2011
  6. maniac103, 08.04.2011 #6
    maniac103

    maniac103 Android-Lexikon

    Beiträge:
    1,237
    Erhaltene Danke:
    1,157
    Registriert seit:
    24.01.2011
    Der Service-Teil davon sieht mir überflüssig aus ... warum registrierst du den Listener nicht direkt im Manifest (halt nicht als PhoneStateListener, sondern als BroadcastReceiver auf android.intent.action.PHONE_STATE)?

    Sieht soweit ok aus. Den Intent würde ich aber so initialisieren:
    Code:
    Intent pService = new Intent(context, PhoneService.class);
    
    Es wäre hilfreich, wenn du den Backtrace (aus dem Logcat) posten könntest ;)
     
  7. sem_thesis, 08.04.2011 #7
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Jetzt habe ich die folgende Fehlermeldung bekommen
    CallClassification wird gar nicht geloggt!
    Es werden immer noch die alte Nummer/Name/Dauer im Log angezeigt.
     
    Zuletzt bearbeitet: 08.04.2011
  8. sem_thesis, 08.04.2011 #8
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Verstehe nicht ganz was du meinst.

    Das Manifest-File sieht bei mir so aus:
    Code:
    ......
           <!-- Service Declaration Area -->
            
            <service android:name ="com.example.mylog.PhoneServiceReceiver">
                <intent-filter>
                    <action android:name="com.example.mylog.PhoneServiceReceiver">
                    </action>
                </intent-filter>
            </service>
     
             <service android:name ="com.example.mylog.PhoneService">
                <intent-filter>
                    <action android:name="com.example.mylog.PhoneService">
                    </action>
                </intent-filter>
            </service>
                   
            <!-- Receiver Declaration Area -->
            
            <receiver android:name=".ServiceEnabler">
                <intent-filter>
                    <action android:name="android.intent.action.PHONE_STATE"/>
                </intent-filter>
            </receiver>
    
        </application>
        
     
  9. sem_thesis, 09.04.2011 #9
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Hello again!

    Ich hab' einen ganz dummen Fehler im Code entdeckt, aus dem ich nicht schlau werden:

    Code:
        // Specify interpretation of Call-Type
        public String callType(String t)    {
            
            String g = null;
    
            if (t == "1")    g = "Incoming Call";
            if (t == "2")    g = "Outgoing Call";
            if (t == "3")    g = "Missed Call";
    
            return g;
        }
    
    
    
    
    public onStartCommand(Intent intent, int flags, int startId) {
    
            // Collect new Phone Logs //
              
            Cursor c = getContentResolver().query(
                           android.provider.CallLog.Calls.CONTENT_URI,
                           null,
                           null,
                           null,
                           android.provider.CallLog.Calls.DATE+ " DESC");
             c.moveToFirst();
    
             String t = c.getString(c.getColumnIndex(CallLog.Calls.TYPE));
             String callclassification = callType(t);
    
    
             // Log new Phone Logs
    
              Log.d(TAG, callclassification);
    
    
    
    return startId;
    }
    

    Der Log wird nicht ausgeführt - was ist an der convertType Funktion falsch gelaufen?

    Referenz: http://developer.android.com/reference/android/provider/CallLog.Calls.html
     
    Zuletzt bearbeitet: 09.04.2011
  10. sem_thesis, 09.04.2011 #10
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Ok, habe das Problem selber gelöst (ist ja eine Semesterarbeit, also muss ich ja selber auch was tun :winki:

    string == string vergleicht anscheinend Objekte, aber keine String.

    Ich habe die Funktion convertType folgendermassen umgeschrieben:

    Code:
        // Specify interpretation of Call-Type
           public String callType(String t)    {
            
            String g = null;
    
            if ("1".equals(t))    g = "Incoming Call";
            else if ("2".equals(t))    g = "Outgoing Call";
            else if ("3".equals(t))    g = "Missed Call";
    
            return g;   
        }
    
     
  11. maniac103, 11.04.2011 #11
    maniac103

    maniac103 Android-Lexikon

    Beiträge:
    1,237
    Erhaltene Danke:
    1,157
    Registriert seit:
    24.01.2011
    Richtiger Ansatz ;)

    Da besteht aber noch Optimierungspotenzial ;)
    Da ja der Anruftyp laut Doku Integer ist, würde ich ihn mit c.getInt() auslesen und dann mit den - genau zu diesem Zweck vorhandenen - Konstanten direkt vergleichen.
     
  12. maniac103, 11.04.2011 #12
    maniac103

    maniac103 Android-Lexikon

    Beiträge:
    1,237
    Erhaltene Danke:
    1,157
    Registriert seit:
    24.01.2011
    Ist doch eigentlich ganz einfach. Momentan hast du
    - einen Service, der einen
    - PhoneStateListener registriert, der wiederum
    - einen Service aufruft (welcher die Daten verarbeitet)

    Einfacher wäre es, wenn du
    - im Manifest einen BroadcastReceiver auf
    android.intent.action.PHONE_STATE registrierst, der dann
    - den Datenverarbeitungsservice aufruft

    Ergebnis: 1 dauerhaft laufenden Service gespart

    Das ist doch Quatsch. Wenn ein Anruf eingeht, startet dein Receiver, schaut nach, ob das Logging aktiv ist und startet einen Service, der einen Anruflistener registriert (?)

    In meiner App schaue ich im PhoneState-BroadcastReceiver nach, ob das ganze eingeschaltet ist, und starte den Datenverarbeitungsservice nur, wenn das der Fall ist.
     
  13. sem_thesis, 13.04.2011 #13
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Ok. Punkt akzeptiert.

    Ich bin mir sowieso am Überlegen, ob es eine gute Idee ist den PHONE_STATE Listener zu gebrauchen.
    Ich habe bis jetzt 3 Services implementiert: GPS (benutzt ACTION_BOOT_COMPLETED Listener), Contacts-Service (hat keinen Listener) und CallLog-Service (benutzt PHONE_STATE Listener).

    Macht es von Batterie/Speicher sparen nicht mehr Sinn periodische Services zu haben, die Daten regulär (GPS: je 2h, Contacts-Service: jede Woche, CallLog-Service: jeden Tag) sammeln?
    Da könnte man auf einen Listener verzichten und einfach einen Receiver einbauen, der direkt nach Serviceinstallation (+ Bedingung: User hät Präferenz eingeschaltet) den Service startet?

    Ist so was möglich?
     
  14. maniac103, 14.04.2011 #14
    maniac103

    maniac103 Android-Lexikon

    Beiträge:
    1,237
    Erhaltene Danke:
    1,157
    Registriert seit:
    24.01.2011
    Klar, möglich ist so was (Service durch AlarmManager starten lassen). Ob es sinnvoll ist, kann ich dir aber nicht sagen, weil das von deiner Applikation abhängt. In meiner App synchronisiere ich das Anrufprotokoll in den Kalender, und da ist IMO der Listener sinnvoller (ich weiß da ja, wann neue Einträge kommen; die Einträge sollen außerdem möglichst schnell im Kalender aufschlagen).
    Ein generelles 'besser' oder 'schlechter' kann man da nicht festlegen.
     
  15. sem_thesis, 15.04.2011 #15
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Ich habe mich für die Listener-Variante für den CallLogs Service entschieden.

    1.1) AndroidManifest.xml
    Code:
    <receiver android:name="com.socialmine.mergedservices.PhoneServiceReceiver">
                <intent-filter>
                    <action android:name="android.intent.action.PHONE_STATE"/>
                </intent-filter>
    </receiver>
    
    1.2) PhoneServiceReceiver.java
    Code:
        @Override
        public void onReceive(Context context, Intent intent) 
        {
                // Define context globally to allow access from private class MyPhoneStateListener
            
                cName = context;
                
                // Put a Listener on the Phone-State
    
                telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                phoneListener = new MyPhoneStateListener();
                telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
                Log.d(TAG, "Listener created");
    
            
        }
    
    1.3) MyPhoneStateListener
    Code:
        //////// Private Class MyPhoneStateListener /////////
        
        private class MyPhoneStateListener extends PhoneStateListener {
            
    
              
              public void onCallStateChanged(int state,String incomingNumber){
                  
    
                  Log.d(TAG, "STATE HAS CHANGED!");
    
                switch(state)    {
                      case TelephonyManager.CALL_STATE_IDLE:
                          Log.d(TAG, "Phone is inactive - IDLE state");
                          
                        // Here comes the actual Service-Functionality
                        
                        Intent pService = new Intent();
                        pService.setAction("com.socialmine.mergedservices.PhoneService");
    
                        // Waiting time before Log-database is accessed (access only after new changes are stored)
                        int sleep = 5000; 
                        
                        PendingIntent piSync = PendingIntent.getService(cName, 0, pService, 0);
                        Log.i(TAG, "schedulePendingSync: " + piSync.toString());
                        AlarmManager alarm = (AlarmManager) cName.getSystemService(Activity.ALARM_SERVICE);
                        alarm.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + sleep, piSync);
    
                        // End of Service-Functionality
    
                          break;
                      case TelephonyManager.CALL_STATE_OFFHOOK:
                          Log.d(TAG, "Initiated/Accepted Call");
                          break;
                      case TelephonyManager.CALL_STATE_RINGING:
                        Log.d(TAG, "RINGING");
                          break;
                  }
                              
                  
              }
    
        }
    
    
    2) Phoneservice.java

    Code:
    Datenverarbeitungs-Code von vorher


    Ok - was nun passiert, ist, dass bei JEDEM Phone_STATE Wechsel (offhook, ringing, idle) der Receiver startet und eine neue Instanz der MyPhoneStateReceiver-Klasse erstellt wird.
    Somit bekomme ich für jeden Anruf 2-3 Mal Logging + Datenbank-speicherung .. ausserdem crasht die App auch noch...

    Ich will aber, dass die Verarbeitung nur EINMAL pro Gespräch geschieht.
    Kann ich den Receiver direkt auf CALL_STATE_IDLE schalten?
     
  16. sem_thesis, 15.04.2011 #16
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
  17. maniac103, 18.04.2011 #17
    maniac103

    maniac103 Android-Lexikon

    Beiträge:
    1,237
    Erhaltene Danke:
    1,157
    Registriert seit:
    24.01.2011
    Wenn du dir den Code anschaust, ist das von dir beobachtete Verhalten doch auch logisch, oder? ;)

    Ja klar, sag ich doch schon die ganze Zeit :)
    Mal ein Beispiel aus meiner App:

    Code:
    public class PhoneEventReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
    
            if (state != null && state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
                /* es wurde aufgelegt, tue die nötigen Dinge */
            }
        }
    }
    
    Das Ganze noch im Manifest anmelden:

    Code:
            <receiver android:label="@string/receiver_name" android:name="PhoneEventReceiver">
                <intent-filter>
                    <action android:name="android.intent.action.PHONE_STATE"/>
                </intent-filter>
            </receiver>
    
    Fertig.
     
  18. sem_thesis, 18.04.2011 #18
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Achso - ja, ich hab' nicht gewusst, dass man einen Listener DIREKT auf den IDLE-State stellen kann.

    Ja, so funktioniert das natürlich tadellos - danke :)

    Der Grund wieso ich einen 'Zwischen-Service' drin hatte, war, dass dieser ausser dem Listener noch eine CallHistory-Log Funktionalität hatte.

    Ich habe also in der onCreate()-Method noch die alten Logs gesammelt.

    Nun habe ich einfach eine Zusatzklasse 'CallHistory.java' erstellt, welche alle Logs sammelt.

    Die rufe ich jetzt in der MainActivity mit
    Code:
            Intent cHistory = new Intent();
            cHistory.setAction("com.example.mylog.CallHistory");
            getBaseContext().startService(cHistory);   
    
    auf.

    Vorher hat das CallHistory-Loggen funktioniert - nun crasht die App einfach mit einem Nullpointer-Error.
    :confused2:
     

    Anhänge:

  19. sem_thesis, 20.04.2011 #19
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Ok - inzwischen bin ich schon schlauer geworden, was die Angelegenheit betrifft.

    Ich weiss jetzt glaube ich, wieso die App crasht.

    Im CallLog hat man ja nicht nur bekannte, sondern auch unbekannte Nummern von unbekannten Anrufern.

    Code:
            Cursor c = getContentResolver().query(
                       android.provider.CallLog.Calls.CONTENT_URI,
                       null,
                       null,
                       null,
                       android.provider.CallLog.Calls.DATE + " DESC");
            
            if(c.moveToFirst()) {
                
                // Iteration-variable;
                int i = 1;
    
                // Check: Still valid entry left?
                while(!c.isAfterLast()) {        
                    
                    // Collect History
                    long tmp = c.getLong(c.getColumnIndex(CallLog.Calls.DATE));
                    Date d = new Date(tmp);
                    date = formatdate.format(d);
                    time = formattime.format(d);
                    name = c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME));
                    phonenumber = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));
                    tmp1 = c.getString(c.getColumnIndex(CallLog.Calls.DURATION));
                    duration = formatDuration(tmp1);
                     tmp2 = c.getInt(c.getColumnIndex(CallLog.Calls.TYPE));
                     callclassification = callType(tmp2);
      
                                    
                      // Move to the next entry
                    c.moveToNext();    
                    i++;
                }
                
            }
    
            c.close();          
    
    
    Die Cursorquery schlägt fehlt --> die App crasht


    Kann man dieses Problem irgendwie mit einem Exception auffangen?
     
  20. sem_thesis, 22.04.2011 #20
    sem_thesis

    sem_thesis Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    111
    Erhaltene Danke:
    0
    Registriert seit:
    06.03.2011
    Phone:
    Nexus One
    Ok - muss diesen Thread wieder zum Leben erwecken.
    Das Problem ist nicht neu - das hat sicher jeder schon mal erlebt!!
    (Auch wenn ich bisher nichts dazu auf StackOverflow gefunden habe).


    Was macht man, wenn der Cursor auf null zeigt? Exception-Handling für NullPointer?? :|
     

Diese Seite empfehlen