Android Alarm Manager (Wakelock? ) geht nicht

KYL3R

Mitglied
Hallo liebes Forum.
Ich verzweifel inzwischen.
Für mein Nokia hatte ich in J2ME ne app geschrieben, die sms zu ner bestimmten Zeit versendet. So als Übung/Einstieg wollte ich diese nun in android übersetzen, da ich jetzt ein android smartphone habe.

Ein Timer/shedule funktionierte ganz gut, man las aber, dass das ineffizient ist, außerdem ging es nicht, sobald das Handy gesperrt war.

Oft schreibe ich abends eine sms und möchte sie morgens, wenn der Empfänger aufsteht (gegen 6uhr) versenden, ohne dafür selbst wach sein zu müssen. (klar, solche apps gibts kostenlos, ich wills aber zur Übung selbst machen)

Jetzt wollte ich dafür den broadcastReceiver benutzen, bzw. den Alarmmanager, soweit ich gelesen habe brauche ich mich um den wake-lock nicht kümmern, da der alarmmanager garantiert, dass die CPU wach gehalten wird, bis "onReceive" beendet ist.

Also einfach ne klasse geschrieben, Receiver in der manifestdatei registriert, in der onReceive (die Broadcastreceiver überschreibt mittels @override) habe ich dann den code zum versenden der sms.

Das klappt solange die app geöffnet ist, das klappte auch schonmal (hab inzwischen sehr viel probiert, inzwischen gehts nicht mehr glaube ich) dass es im gesperrten modus ging.
Einmal ging es sogar nach 2 Stunden, aber tagsüber, da hab ich das Handy wohl öfter "geweckt" um nach sms/whatsapp nachrichten zu gucken.

Aber was noch nie ging, über nacht (mehrere stunden unangetastet) eine sms versenden. (und genau das möchte ich)

Dann ist das handy vermutlich im stand-by modus... prinzipiell ging es ja, und da es auch dann über den alarm manager geschieht, müsste es auch gehen wenn das handy im sleep mode oder die app sogar aus (statt minimiert) ist, oder ?


Ich habe jetzt tagelang probiert und die API durchforstet, jetzt geht nichtmal mehr das "oneShot"/"alarmController" Beispiel. ich habe iwie alles verpfuscht durchs probieren...

Hat jemand ein funktionierendes Beispielprojekt (am besten für eclipse, den ganzen Ordner, mit Manifest und allem...)

Denn mir raucht der Kopf, das deprimiert wenn es einfach nicht geht... Zumal es in J2ME ging -.- Aber da wurde das ganze "quick and dirty" gelöst, der arme akku...

Ein Tutorial (notfalls auch englisch) wäre gut.

Ich weis nicht obs was zur Sache tut, aber ich kapiere Intents und Pendings intents nicht. "Man sagt, was man vorhat, bzw. später tun möchte" - hä?
Ich kopier das immer aus den Beispielen weil mir das zu dumm ist. Aber vielleicht ists an der Zeit, sich dem Thema mal zu nähern...

Oh Gott hoffentlich erbarmt sich einer den Text zu lesen. ich sollte mich mal kürzer fassen...
 

schlingel

Gesperrter Benutzer
Also, fangen wir bei den Begrifflichkeiten an.

Ein Intent ist, wie der Name schon sagt, eine Absichtserklärung. Wenn du dem System einen Intent schickst, sucht sich dieses dann die passende Aktion heraus. Ein Intent kann sehr allgemein formuliert werden wie z.B. beim Share-Intent, wo dir als Entwickler egal ist ob der Benutzer eine SMS, Email oder einen Tweet wegschickt oder sehr speziell in dem du den vollqualifizierten Klassennamen angibst, damit wirklich nur diese Klasse verwendet werden kann.

Ein PendingIntent ist ein Intent der konserviert wird um später dann abgesendet zu werden. Wofür braucht man das? Z.B. für Notifications die ja erst den Intent feuern können wenn der Benutzer draufklickt oder eben für Alarme.

Jetzt zu deinem Problem:
soweit ich gelesen habe brauche ich mich um den wake-lock nicht kümmern, da der alarmmanager garantiert, dass die CPU wach gehalten wird, bis "onReceive" beendet ist.

Das stimmt. Wenn Threads in's Spiel kommen allerdings nicht mehr. Denn diese Garantie gilt nur für den Main-Thread, startest du deine Aktion in einem AsyncTask oder einer eigenen Thread-Implementierung wird der Wake-Lock natürlich wieder freigegeben obwohl der Thread noch läuft.

Einfacher Test: Selbst einen Wake-Lock anfordern und diesen extra freigeben.

Was genau falsch läuft ist natürlich schwer zu sagen ohne Code. Poste doch denn Code vom onReceive. Offensichtlich wird dieser ja aufgerufen.
 

KYL3R

Mitglied
Der Code sollte nicht besonders groß werden, noch dazu hörte ich das mit den threads, weshalb ich alles in eine Klasse gequetscht habe:

Manifest.xml :
[XML]<?xml version="1.1" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="timedSMS.core"
android:versionCode="2"
android:versionName="2.1" >

<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.SEND_SMS">
</uses-permission>
<uses-permission android:name="android.permission.READ_CONTACTS">
</uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK">
</uses-permission>
<application
android:icon="@drawable/ic_timed2"
android:label="@string/app_name" >
<activity
android:name=".TimedSMSActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<receiver android:process=":remote" android:name=".TimedSMSActivity">
</receiver>
</activity>
</application>
<receiver android:name=".TimedSMSActivity">
</receiver>
</manifest>[/XML]

-Wake lock kann ich da jetzt rausnehmen oder ? da ich alarmmanager nutze ?

Ich habe einmal den receiver (die mainklasse) unter </intent-filter> als ":remote" registriert und nochmal unter " </application>
<receiver android:name=".TimedSMSActivity">
</receiver>"

und dann NOCHMAL dynamisch :
registerReceiver(alarmReceiver, myFilter);

hält doppelt besser, oder stört sich das hier ? das kam druchs viele rumprobieren zustande, da es ja nie richtig ging...

Code :
Ich rufe diese Methode auf, wenn die Zeit eingegeben wurde, hole sie mir mit der methode giveMeTheChosenTime().
Hier die methode zum setzen :
Java:
private void setAlarmAtTime() {
		registerReceiver(alarmReceiver, myFilter);

        Myintent = new Intent(ACTION_NAME);        

        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,Myintent, PendingIntent.FLAG_ONE_SHOT);

        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, giveMeTheChosenTime(), pendingIntent);
        Toast.makeText(this, "Alarm set", Toast.LENGTH_LONG).show();
		
	}


meine onReceive ist in dem Broadcastreceiver, der ebenfalls in der Main Klasse ist :

Java:
BroadcastReceiver alarmReceiver = new BroadcastReceiver() {
		
		@Override
		public void onReceive(Context context, Intent intent) {
			//PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
			Toast.makeText(context, "Alarm worked", Toast.LENGTH_LONG).show();

//			PendingIntent pi = PendingIntent.getActivity(context, 0,Myintent, 0);
//			SmsManager sms = SmsManager.getDefault();
//			sms.sendTextMessage(nummerText, null, nachrichtText, pi, null);

			nm = (NotificationManager) context
		    .getSystemService(Context.NOTIFICATION_SERVICE);
		  CharSequence from = "Nithin";
		  CharSequence message = "Crazy About Android...";
		  PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
		    new Intent(), 0);
		  Notification notif = new Notification(R.drawable.ic_timed2,
		    "Ich schaffe das noch...", System.currentTimeMillis());
		  notif.defaults = Notification.DEFAULT_SOUND;
		  notif.setLatestEventInfo(context, from, message, contentIntent);
		  nm.notify(1, notif);
		}
	};

Bemerke: Der "sms-senden"-code ist auskommentiert, stattdessen hab ich gerade eine notification, weil ich dachte, wer weiß, vielleicht hat meine app im sleepmode keinen empfang oder so...
Der scheint (nach jüngsten tests) zu funktionieren, habe aber noch nicht länger als 10 min getestet. Aber app konnte minimiert und handy gesperrt sein.


Jetzt müsste es an den intents beim sms-versand scheitern, so wie ich das sehe.

Bitte darum, das auf Richtigkeit zu prüfen :)
 

KYL3R

Mitglied
Wissend, dass das Problem jetzt nur noch am sms-senden hängen kann, untersuchte ich eben diese Funktion mit gesonderter Aufmerksamkeit. Ich weitete die Tests aus und fand den Ursprung des Problems, die Lösung ist lächerlich einfach.

Problem / Auftreten:
OnReceive versendete mit meinem sms-code die sms nur an eine bestimmte Person, wenn ich nicht länger als ein paar Minuten wartete, an mich selbst, konnte ich auch nach stunden und über Nacht (Handy müsste dann längst im standby-modus sein) versenden.

Lösung:
Java:
String nummer;
//Zuweisung
nummer.replace("+49", "0");

Erklärung:
Die Person, bei der es nicht funktionierte, hatte in meinem Telefonbuch eine "+49..."-nummer zugewiesen bekommen.
Verwirrend war, dass dies keinerlei Problem herbeiführte, wenn der Zeitraum klein war (das Handy nicht "schlafen" geht). Außerdem erfordert die sms-sende-methode einen String, statt einem int für die Nummer. Verstehen, kann ich es nicht, aber das Problem ist nun folgendes, wenn das Handy in den Stand-by modus geht, muss im Alarmmanager der String irgendwie falsch/anders gespeichert werden, vielleicht wird er als Zahl aufgefasst, vielleicht wird das "+" falsch interpretiert... Das hat jedenfalls zur Folge, dass die sms-sende-methode eine Exception wirft, wenn sie mit DIESEM Parameter aufgerufen wird.

Ich hatte immer nach dem Senden mein Programm, was vorher im Hintergrund lief, beendet. Die Exception meldet sich (da es auf dem Handy keine Konsole gibt) nicht, das Programm wird nur geschlossen. Daher ist mir das erst nicht aufgefallen.
Der entscheidene Hinweis war dann, dass das Programm zwar im Taskmanager beendet war, aber beim öffnen alle Feldeinträge noch vorhanden waren. Außerdem funktionierte es bei meiner Nummer, die mit einer 0 Beginnt und bei der Person mit +49 nicht. Was mich zwar prinzipiell nicht stutzig machte, aber letztendlich doch ausgetestet und zur Fehlerbehebung geführt hat.

Danke für die Mitarbeit, ich hoffe der Beitrag hilft eines Tages jemandem.
 

Neue Themen


Oben