Konzept meiner App

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Konzept meiner App

    Hallo Community

    Weil ich auf meinem Galaxy S9 ein Prepaid-Surf-Abo gelöst habe und unterwegs gelegentlich vergesse, die Mobile Daten auszuschalten, was mein Surf-Konto plündert, möchte ich eine App schreiben, die mir genau dann eine Notification (oben links) anzeigt, wenn "Mobile Daten" eingeschaltet ist. Es ist mir als Anfänger gelungen, als Teillösung eine App zu schreiben, die beim Ausführen diese Notification anzeigt, wenn "Mobile Daten" eingeschaltet ist, bzw. löscht, wenn nur WLAN eingeschaltet ist. Aber ich scheitere daran, jetzt daraus eine selbständige App zu machen, die das Gewünschte liefert, auch weil ich bis jetzt in meinem Leben nur zwei Apps mit je einer einzigen Klasse geschrieben habe. Vielleicht kann mir aber der eine Profi eine oder mehrere der folgenden Fragen beantworten, die auch nicht in meinem Lehrbuch behandelt werden. Danke für jeden Tipp, insbesondere auch Hinweise, wo und wie ich mich zu diesen Themen schlau machen kann ...

    1) Vermute ich richtig, dass die beste Form für meine Idee ein Service wäre, der unsichtbar permanent im Hintergrund läuft? Wenn ja: Ich habe noch nie einen Service geschrieben, gibts irgend wo eine einfachere Anleitung/ein Beispiel?

    2) Kann meine App die Aktionen "Mobile Daten ein" bzw. "Mobile Daten aus" abfangen, so dass meine App entsprechend mit der Notification reagieren kann, oder muss meine App selber z.B. jede Sekunden testen, ob "Mobile Daten" ein- oder ausgeschaltet ist?

    3) Um jede Sekunde einen Code auszuführen, habe ich im Internet folgende Lösung gefunden. Aufruf der Klasse "Test" in der MainActivity OnCreate-Methode mittels

    Quellcode

    1. Test test = new Test();
    Und hier die Klasse "Test" (erzeugt alle Sekunden einen Pieps):

    Quellcode

    1. public class Test extends TimerTask {
    2. public Test() {
    3. Timer timer = new Timer();
    4. timer.scheduleAtFixedRate(this, 0, 1000);
    5. }
    6. public void run(){
    7. ToneGenerator toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
    8. toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP,150);
    9. }
    10. public static void main(String[] args) {
    11. new Test();
    12. }
    13. }
    Alles anzeigen
    Das funktioniert, führt aber nach ca. 20 Repetitionen zu einem Absturz. Warum? Speicherproblem? Aus dem Logcat werde ich nicht klug:

    Quellcode

    1. 11-12 16:31:12.910 6308-6376/my.apps1.tfvrb W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount 1920 -> 1920
    2. 11-12 16:31:12.911 6308-6376/my.apps1.tfvrb I/AudioTrack: FastTrack denied resize maxNoti fc 960, new 960, enable throttle
    3. 11-12 16:31:12.911 6308-6376/my.apps1.tfvrb D/AudioTrack: Client defaulted notificationFrames to 960 for frameCount 1920
    4. 11-12 16:31:13.050 6308-7223/my.apps1.tfvrb D/AudioTrack: stop() called with 7680 frames delivered
    5. 11-12 16:31:13.910 6308-6376/my.apps1.tfvrb E/AudioTrack: AudioFlinger could not create track, status: -12
    6. 11-12 16:31:13.913 6308-6376/my.apps1.tfvrb E/ToneGenerator: AudioTrack(0x7cf2cb8c00) set failed with error -12
    7. ToneGenerator init failed
    8. 11-12 16:31:13.917 6308-6376/my.apps1.tfvrb E/AndroidRuntime: FATAL EXCEPTION: Timer-0
    9. Process: my.apps1.tfvrb, PID: 6308
    10. java.lang.RuntimeException: Init failed
    11. at android.media.ToneGenerator.native_setup(Native Method)
    12. at android.media.ToneGenerator.<init>(ToneGenerator.java:863)
    13. at my.apps1.tfvrb.Test.run(Test.java:74)
    14. at java.util.TimerThread.mainLoop(Timer.java:555)
    15. at java.util.TimerThread.run(Timer.java:505)
    Alles anzeigen

    4) Der folgende Code für das Erzeugen/Löschen der Notification funktioniert, wenn ich ihn in der MainActivity in der onCreate-Methode schreibe. Wenn ich diesen Code aber in die obige Klasse "Test" anstelle des Pieps von Zeile 9/10 schreibe, erhalte ich Fehler:
    Zeile 1: getApplicationContext() cannot resolve method
    Zeile 3 und 19: getSystemService(this.NOTIFICATION_SERVICE) cannot resolve method
    Zeile 10: MainActivity.this not an enclosing class

    Auch da weiss ich leider nicht, wie ich das abändern muss, damit der Code in der Klasse "Test" anstelle des Pieps läuft.


    Quellcode

    1. if (Settings.Global.getInt(getApplicationContext().getContentResolver(), "mobile_data", 0) == 1) {
    2. NotificationManager notificationManager = (NotificationManager) getSystemService(this.NOTIFICATION_SERVICE);
    3. String channelId = "mobile_datenverbindung";
    4. CharSequence channelName = "Mobile Datenverbindung";
    5. int importance = NotificationManager.IMPORTANCE_LOW;
    6. NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, importance);
    7. notificationManager.createNotificationChannel(notificationChannel);
    8. int notifyId = 1;
    9. Notification notification = new Notification.Builder(MainActivity.this)
    10. .setContentTitle("ACHTUNG! Mobile Datenverbindung ist an!")
    11. .setSmallIcon(R.drawable.tfvrbklein)
    12. .setChannelId(channelId)
    13. .build();
    14. notificationManager.notify(notifyId, notification);
    15. } else {
    16. NotificationManager notificationManager = (NotificationManager) getSystemService(this.NOTIFICATION_SERVICE);
    17. String channelId = "mobile_datenverbindung";
    18. NotificationChannel notificationChannel = notificationManager.getNotificationChannel(channelId);
    19. notificationManager.deleteNotificationChannel(channelId);
    20. }
    Alles anzeigen


    Danke an alle, die sich bis hierher durchgekämpft haben!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Desperate ()

  • Hallo

    Zu Frage 1 ich würde sagen das da ein Broadcast Receiver besser geeignet ist.
    Das System versendet BroadcastIntenst die du mit einem Receiver abfangen kannst.
    Die Action “ACTION_AIRPLANE_MODE_CHANGED” könnte da nützlich sein.
    developer.android.com/guide/components/broadcasts
    big-app.de/broadcast-receiver-in-android/


    Frage 2 ist eigentlich mit frage 1 beantwortet. Direkt abfangen glaube nur über eine Callback Methode. Aber du bekommst ja eine Änderung der Airplane und somit des Netzwerks mit, über den Receiver und kannst dann selber prüfen.


    Frage 3 der Code ist bestimmt aus einen Beispiel für eine Desktop Anwendung nicht für Android denn in Android gibt es keine Main() Methode.
    Der Timer läuft im Main Thread .


    Frage 4
    Du bist in einer anderen Klasse die von Thread erbt und nicht von Activity.
    Du hast hier keinen Kontext der Activity .
    Den müsstest du den Konstruktor mitgeben Instanzieren der Klasse.
    Aber wie so willst du eine Notification in einem eigenen Thread machen?


    Hier noch ein Link zu einem PDF
    wo dir auch der Broadcast Receiver erklärt wird.

    google.com/url?sa=t&rct=j&q=&e…Vaw2AyQzU4KCAtBvdAksDs80S
    Ein Feedback auf Tipps ist auch schön. :P
  • Danke, Jogimuc, für deine Einschätzung und die interessanten Links. Damit habe ich eine saftige Hausaufgabe, die mich mal ein paar Tage oder Wochen beschäftigen wird ... Anhand eines eigenen, konkreten Problems zu lernen ist aber wohl die motivierendste Art, zu lernen.

    Einzig eine Frage ist (im Moment) noch nicht beantwortet. Ich hätte sehr gern gewusst, warum mein obiger unter 3) aufgelisteter Code nach etwa 20 Repetitionen crasht. Da der Pieps 20-mal ertönt, kann der Code ja nicht grundsätzlich falsch sein. Wird der Speicher knapp, da immer neue Instanzen erzeugt und die alten nicht gelöscht werden?
  • Hallo

    Du startest den Timer in dem Konstruktor der Klasse TimerTask der läuft aber noch im Ui Thread. Die onRun läuft im eigenen Thread.
    Der Timer läuft wohl zu lange und erzeugt dadurch eine ANR.
    Welche Fehlermeldung ist denn im Log?

    Und lasse die Main Methode weg die bauchst du nicht. Wird bei einer Dektop anwendung benutzt nicht bei Android.


    Quellcode

    1. // in der Activity
    2. Timer timer = new test();
    3. timer.scheduleAtFixedRate(this, 0, 1000);
    4. public class Test extends TimerTask {
    5. public void run(){
    6. ToneGenerator toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
    7. toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP,150);
    8. }
    9. }
    Alles anzeigen
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von jogimuc ()

  • Ok, jogimuc, ich hab jetzt mal die Timer-Geschichte in meine MainActivity eingebaut (leicht andere Syntax als du schreibst - ich denke, bei dir sind noch ein paar Flüchtigkeitsfehler drin):

    Quellcode

    1. Timer timer = new Timer();
    2. TimerTask test = new TimerTask() {
    3. @Override
    4. public void run() {
    5. ToneGenerator toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
    6. toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP,150);
    7. }
    8. };
    9. timer.scheduleAtFixedRate(test,0, 1000);
    WIeder stürzt aber das Programm nach etwa 20 Sekunden (=20 Piepse) ab. Das Logcat habe ich schon im Posting Nr. 1 beigefügt (vielleicht irritiert dort der Titel "Quellcode", aber ich habe diese Darstellung als Code gewählt, weil dann die Zeilen numeriert werden und man so leicht darauf verweisen kann). Die ersten ca. 3 Zeilen gehören noch zum letzten Pieps, dann entgleist die App offensichtlich.

    Danke fürs Anschauen!
  • versuche es mal so

    Quellcode

    1. public class MainActivity extends AppCompatActivity {
    2. @Override
    3. protected void onCreate(Bundle savedInstanceState) {
    4. super.onCreate(savedInstanceState);
    5. setContentView(R.layout.activity_main);
    6. Timer timer = new Timer();
    7. timer.scheduleAtFixedRate(new Test(), 0, 1000);
    8. }
    9. public class Test extends TimerTask {
    10. ToneGenerator toneGen1;
    11. public Test() {
    12. toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
    13. }
    14. public void run(){
    15. toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP,150);
    16. }
    17. }
    18. }
    Alles anzeigen
    Ein Feedback auf Tipps ist auch schön. :P
  • Wunderbar, Riiiiesendank, jogimuc, das funktioniert ^^ . Jetzt konnte ich auch die Piepserzeugung durch meinen minütlichen Test, ob "Mobile Daten" eingeschaltet sind, ersetzen. (Noch) nicht elegant, aber tut vorerst das, was ich will. Ich habe aber gemerkt, dass ich alles noch zu wenig gut verstehe, warum der Code gerade so lauten muss, und ich verschwinde mal in der Versenkung, um mich etwas schlauer zu machen. Vielleicht ist das Projekt mit dem Broadcast Receiver im Moment noch zu gross für mich. Wir werden sehen...

    Bis ein anderes Mal...
  • Hallo cl500merza

    Danke für das Lob. Ich bring das schon noch fertig, das ist ja die Herausforderung und das, was schlussendlich Spass macht (ist nicht mien Job, nur mein Hobby). Eine Version, die minütlich den Status abfragt, läuft ja schon auf meinem S9. Aber ich habe kein Patent auf meiner Idee (die wohl andere auch schon hatten), wenn du deinem Kumpel den Tipp geben willst - nur zu.

    Schöner Tag