Problem mit Thread bei Galaxy S5 und S6(Edge)

A

Andi0310

Neues Mitglied
0
Hallo zusammen.

Ich habe ein Problem.
Ich programiere gerade ein Game mit Android Studio 2.2.

Es soll eine Digitaluhr in der rechten oberen Ecke ausgegeben werden, wegen dem Zeichenabstand habe ich Vier Buttons(die Uhr soll auch anklickbar sein) eingefügt.

Nun zum eigentlichen Problem.

Auf Galax Tab 2 (Android 4.2) und Tab 4 (Android 5) läuft die App einewand frei.Hier gibt es keine Probleme.
aber auf Galaxy S5(Android 6.0.1) und S6(Android 6.0.1) läuft sie wenn man sie aus der Installation heraus startet auch ohne Probleme.
Öffne ich sie dann aber vom App-Display aus stürzt der Thread ab.

Ich kann auch nicht Debugen, weill dabei die App immer neu istalliert wird dann gleich gestartet wird (wo sie ja funktioniert.).

Nun der Code zur entsprechenden Activity.

Code:
public class OfficeActivity extends Activity
{
    public GameClass daten;

    public Button hour1,hour2,minute1,minute2,doppelP;

    String timebuffer;

    public Thread thread;
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        // TODO: Implement this method
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.office);
        
        daten=new GameClass(getIntent());

        hour1 = (Button) findViewById(R.id.hours1buero);
        hour2 = (Button) findViewById(R.id.hours2buero);
        minute1 = (Button) findViewById(R.id.minutes1buero);
        minute2 = (Button) findViewById(R.id.minutes2buero);
        doppelP = (Button) findViewById(R.id.doppelpunktbuero);

        Typeface myFont = Typeface.createFromAsset(getAssets(), "fonts/myfontz.ttf");
        doppelP.setTypeface(myFont);
        hour1.setTypeface(myFont);
        hour2.setTypeface(myFont);
        minute1.setTypeface(myFont);
        minute2.setTypeface(myFont);

        addListenerOnButton();
        
        gameloop();
    }
    
    public void gameloop()
    {
        final Handler handler=new Handler();
        new Thread(new Runnable()
        {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {}
                    thread = Thread.currentThread();
                    daten.Secunds += 1;
                    if (daten.Secunds >= 60 / daten.timeSpeed) {
                        daten.TimeMinutes++;
                        daten.Secunds = .0f;
                    }
                    if (daten.TimeMinutes > 59) {
                        daten.TimeHours += 1;
                        daten.TimeMinutes = 0;
                    }
                    if (daten.TimeHours > 23)
                        daten.TimeHours = 0;
                    if (daten.TimeHours < 10) timebuffer = "0" + daten.TimeHours;
                    else timebuffer = "" + daten.TimeHours;
                    if (daten.TimeMinutes < 10) timebuffer += "0" + daten.TimeMinutes;
                    else timebuffer += daten.TimeMinutes;

                    handler.post(new Runnable() {
                        @Override
                        public void run()
                        {
                            // Hier läuft alles ab.

                            hour1.setText("" + timebuffer.charAt(0));
                            hour2.setText("" + timebuffer.charAt(1));
                            minute1.setText("" + timebuffer.charAt(2));
                            minute2.setText("" + timebuffer.charAt(3));

                            gameloop();
                        }
                    });
                }
        }).start();    // Hier wird der Threat gestartet.
    }

Kann mir jemand helfen ?
 
Hallo Andi,

man kann hier nur vermuten, wir sehen nicht den gesamten code

a) Da Du explizit von 6.x sprichst : Berechtigungen manuell gesetzt ???
b) Was machst du denn in deiner GameClass ??? und warum übergibst du der getIntent() ? (???)
c) Deinen Thread würde ich eher in einen Async umbauen , und ggf. ein runOnUiThread(new Runnable() verwenden
d) Debugging im thread ist immer tricky, aber du könntest doch via ADB / USB logs ausgeben , dann weisst du doch wo es hängt.


P.S Ich kann mir auch nicht vorstellen , dass es kein errorlog geben soll - poste den doch mal hier

lg
Stefan
 
Zuletzt bearbeitet:
Habe die App jetzt mal bei während laufendem Logcat auf dem S6 aus dem App Display heraus gestartet und beim Absturz konnte ich folgendes abfange.
GetIntend wird übergeben, weill die Activity von einer anderen aus gestartet wird und ich habe die Class GameDaten erstellt, weill ich nicht immer die Variablen in jeder Activity neu von Hand füllen möchte damit ist auch kein Problem.


: ActivityRecord{7fab063 token=android.os.BinderProxy@2954eeb {com.Factory/com.Factory.challengeActivity}} show : false
09-23 17:57:42.181 15739-15949/com.Factory E/AndroidRuntime:
FATAL EXCEPTION: Thread-4970
Process: com.Factory, PID: 15739
java.lang.ArithmeticException: divide by zero
at com.Factory.OfficeActivity$1.run(OfficeActivity.java:62)
at java.lang.Thread.run(Thread.java:818)
09-23 17:57:42.241 15739-15770/com.Factory D/mali_winsys: new_window_surface returns 0x3000, [2560x1440]-format:1
09-23 17:57:42.261 15739-15739/com.Factory I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@2954eeb time:33282328
09-23 17:57:42.531 15739-15739/com.Factory D/ViewRootImpl: #3 mView = null

Vieleicht ist das hilfreich ?
Danke.

Wie gesagt aus Installation direct heraus läuft die App ohne Probleme.Aber ich möchte sie ja nicht jedesmal wenn ich sie benutzen will neu installieren.
[doublepost=1474647042,1474646970][/doublepost]RunOnUiThread habe ich auch schon ausprobiert mit dem selben Ergebniss.
 
java.lang.ArithmeticException: divide by zero

da ist doch der Fehler - dein divider ist 0;
Zeile 62

Da du das aus deiner gameclass nimmst , kann ich nicht sagen , was da schief läuft

ergo : bau dir mal ein paar Exeptions ein

weill ich nicht immer die Variablen in jeder Activity neu von Hand füllen möchte
Dazu wäre aber eine Singleton besser- vielleicht tritt genau deshalb der Fehler auf




P.S. ich bleibe dabei : da dies ein ständiger Thread ist , kann ich nur anraten da einen AsynTask zu verwenden und den auf alle Fälle mit AsyncTask.THREAD_POOL_EXECUTOR - dein jetztiger construct läuft irgendwann mal aus dem Ruder
 
Zuletzt bearbeitet:
Und das wird die betreffende Stelle sein:
Code:
thread = Thread.currentThread();
                    daten.Secunds += 1;
                    if (daten.Secunds >= 60 / daten.timeSpeed) { // Hier dürfte die Grund für den Absturz liegen.
                        daten.TimeMinutes++;
                        daten.Secunds = .0f;
                    }
 
Hallo.

Hatte gestern leider keine Zeit mehr mich wieder zu melden.
Genau die Stelle betrifft es auch.

Das Problem ist nur der Transport der Daten von einer Activity zur anderen.


Code:
public class GameClass
{
    public GameClass(Intent intent)
    {
        Bundle bundle=intent.getExtras();
                
        AnzRestMax=6;
        Secunds=0;
        
        if(bundle!=null)
        {
            timeSpeed=bundle.getByte("timespeed");
            TimeMinutes=bundle.getByte("timeminutes");
            TimeHours=bundle.getByte("timehours");
            status=bundle.getBoolean("status");
            Schwierigkeit=bundle.getByte("dificult");
            Challenge=bundle.getByte("challenge");
            anzRest=bundle.getByte("anzrest");
        {
        else
        {
            timeSpeed=5;
            TimeMinutes=20;
            TimeHours=9;
            status=false;
            Schwierigkeit=0;
            Challenge=0;
            anzRest=6;
            
        }
    }
    
    public Bundle writeToBundle(Bundle bundle)
    {
        bundle.putByte("timespeed",timeSpeed);
        bundle.putByte("timeminutes",TimeMinutes);
        bundle.putByte("timehours",TimeHours);
        bundle.putBoolean("status",status);
        bundle.putByte("dificult",Schwierigkeit);
        bundle.putByte("challenge",Challenge);
        bundle.putByte("anzrest",anzRest);
        return bundle;
    }

und der aufruf in jeder Klasse ist folgendermassen.

Code:
button4.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View arg0)
                {
                    Intent intent=new Intent(context,OfficeActivity.class);
                    intent.putExtras(daten.writeToBundle(bundle));
                    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                    pendingIntent.send(getApplicationContext(), 0, intent);
                }
            });

Werde zusehen ob ich das ganze noch mit ein Paar Exeptions bestücke. Aber dort muss ja irgendwo schon ein Fehler sein.
 
Der Fehler liegt nicht dort, sondern im Konzept der Uhr in der App.
Du hast eine Variable, die 0 ist, trotzdem sie einen anderen Wert haben sollte. Diese Variable ist ein primitiver Datentyp, und ist ein Attribut der Klasse.
Wenn unter Java der Datentyp int keine Referenz mehr hat, wird ihm der Wert 0 zugewiesen. Also sind in Deinem Fall Referenzen in der App verschwunden.

Der Fehler tritt auf, nachdem die App pausiert hat. So wie ich das sehe, beendest du den Thread für deine Uhr nicht, wenn die App pausiert. Beim aufwecken der App fehlen Referenzen, die der Garbage Collektor (GC) weggeräumt hat, das führt zum Absturz. Und bei neuen, schnellen Device ist der GC aggressiver (Stromsparen :) ), weshalb die App auf Tablets mit langsamen CPUs und alten Versionen läuft.
Das heißt, du muss deinen Thread beenden. Und dann neu starten.

Die Uhr in einen Thread auszulagern, ist auch so keine gute Idee. Threads werden unregelmäßig vom System aufgerufen, sprich das ganze ist auch noch ungenau. Benutze lieber die Systemzeit.
 
  • Danke
Reaktionen: swa00
Nachtrag: Die Methode getIntent() kann es nicht sein, weil onCreate() beim Restart der App nicht aufgerufen wird.
Activity | Android Developers
 
Hallo markus.tullius.
Habe mir mal asynTask mal angeschaut und werde das ganze vieleicht darauf umbauen.
Eine Frage. Da AsynTask als Instance des UI Task (in der Activity) agelegt werden muss ist es auch so, dass er seine gültigkeit verliert, wenn die Activity ihre Gültigkeit verliert z.B. andere Activity gestartet wird.
Liege ich da richtig ?
 
  • Danke
Reaktionen: swa00
Nabend Markus,

jetzt muss ich dich doch mal an der Stelle fragen ....

Da der Thread Hauptbestandteil von AsyncTask ist, warum soll man diesen nicht verwenden,
insbesondere , wenn er mit executeOnExecutor (nicht execute) initialisiert worden ist.

Gerade weil er mit der GUI und dem Mainthread communiziert habe ich auch AsyncTask empfohlen
Das doch mE. weit einfacher für ihn .


lg
Stefan

.
 
Zuletzt bearbeitet:
Für längere Rechenoperationen ist der AsyncTask nicht ausgelegt. Er ist zwar einfach, aber kein vollwertiger Ersatz. Wenn man sauberen Programmcode programmieren will, kommt man um Threads nicht herum. Leider. :(

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.)
AsyncTask | Android Developers
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: swa00
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.)

Shit, den Satz habe ich überlesen
Jetzt wird auch verständlicher warum man irgendwann executeOnExecutor realisiert hat.

@Andi : ich nehme natürlich die Empfehlung für AsyncTask für dein Vorhaben zurück und ein Sorry an dieser Stelle

@Markus : ich Danke dir

lg
Stefan
 
@swa00: Wenn es dich tröstet, ich haben ihn beim ersten mal auch überlesen. ;)
 
Wenn es dich tröstet, ich haben ihn beim ersten mal auch überlesen

Dadurch ist mein Selbstbewusstsein wieder hergestellt :)
 

Ähnliche Themen

D
Antworten
17
Aufrufe
326
datNeMo
D
Muecke1982
Antworten
8
Aufrufe
1.009
Skyhigh
Skyhigh
S
Antworten
4
Aufrufe
956
Sempervivum
S
Zurück
Oben Unten