trotz invalidate() wird onDraw() nicht aufgerufen

phobos

Mitglied
Ich versteh absolut nicht warum invalidate() auf einmal meine onDraw() Methode in meiner Panel Klasse nicht mehr aufruft. Es hatte schon mal funktioniert aber jetzt wird onDraw nur noch einmal und dann nie wieder aufgerufen. obwohl invalidate() ständig aufgerufen wird.

Java:
package org.phobos.kompass;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.Window;
import android.widget.TextView;

public class KompassActivity extends Activity implements SensorEventListener {

	private SensorManager mSensorManager;
	private Sensor mOrientation;
	private Panel mPanel;
	TextView textFenster;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.main);
		AttributeSet attrs = null;
		mPanel = new Panel(this, attrs);
		mPanel.setRoll_angle(0);
		mPanel.setAzimuth_angle(0);
		textFenster = (TextView) findViewById(R.id.textView1);
		mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);

	}

	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// Do something here if sensor accuracy changes.
		// You must implement this callback in your code.
	}

	@Override
	protected void onResume() {
		super.onResume();
		mSensorManager.registerListener(this, mOrientation,
				SensorManager.SENSOR_DELAY_NORMAL);
	}

	@Override
	protected void onPause() {
		super.onPause();
		mSensorManager.unregisterListener(this);
	}

	public void onSensorChanged(SensorEvent event) {

		float azimuth_angle = event.values[0];
		float pitch_angle = event.values[1];
		float roll_angle = event.values[2];

		//  Text ausgeben
		// "Azimuth:" + String.format("%.2f", azimuth_angle) + "°", 0, 50,
		// "x-Neigung:" + String.format("%.2f", pitch_angle) + "°", 0,
		// 100, mPaint);
		// "y-Neigung:" + String.format("%.2f", roll_angle) + "°",
		// 0, 150, mPaint);
		textFenster.setText("Azimuth: " + String.format("%.2f", azimuth_angle)
				+ "°");
		
		mPanel.setRoll_angle(roll_angle);
		mPanel.setPitch_angle(pitch_angle);
		mPanel.setAzimuth_angle(azimuth_angle);
		mPanel.invalidate();
	}

}


Java:
package org.phobos.kompass;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

// Diese Klasse ist für das Zeichnen auf dem Display zuständig

public class Panel extends View {

	// Variablen deklarieren
	private int xpos; // Position der
	private int ypos; // Kugel
	private float pitch_angle; // Sensordaten
	private float roll_angle;
	private float azimuth_angle;

	// Konstruktor
	public Panel(Context context, AttributeSet attrs) {
		super(context, attrs);

	}

	// In der onDraw Methode wird auf den Bildschirm gezeichnet
	@Override
	public void onDraw(Canvas canvas) {

		// // kleine Pause zum Akku sparen
		// try {
		// Thread.sleep(33);
		// } catch (InterruptedException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }

		// Hintergrund zeichnen
		Bitmap background = BitmapFactory.decodeResource(getResources(),
				R.drawable.background);
		Rect dst = new Rect();
		dst.set(0, 0, canvas.getWidth(), canvas.getHeight());
		canvas.drawBitmap(background, null, dst, null);

		// Kompass drehen und zeichnen
		Bitmap komp = BitmapFactory.decodeResource(getResources(),
				R.drawable.kom_blatt);
		Matrix mat = new Matrix();
		mat.postRotate(360 - azimuth_angle);
		Bitmap komp_gedr = Bitmap.createBitmap(komp, 0, 0, komp.getWidth(),
				komp.getHeight(), mat, true);
		int xversatz = (komp_gedr.getWidth() - komp.getWidth()) / 2;
		int yversatz = (komp_gedr.getHeight() - komp.getHeight()) / 2;
		canvas.drawBitmap(komp_gedr, canvas.getWidth() / 2 - komp.getWidth()
				/ 2 - xversatz, canvas.getHeight() / 2 - komp.getHeight() / 2
				- yversatz, null);

		// Kugelposition berechnen und zeichnen
		Bitmap kugel = BitmapFactory.decodeResource(getResources(),
				R.drawable.fadenkreuz);
		xpos = (canvas.getWidth() / 2)
				+ Math.round((roll_angle / 180) * canvas.getWidth())
				- kugel.getWidth() / 2;
		ypos = (canvas.getHeight() / 2)
				+ Math.round((pitch_angle / 180) * canvas.getHeight())
				- kugel.getHeight() / 2;
		canvas.drawBitmap(kugel, xpos, ypos, null);

	}

	// Getter und Setter

	public float getPitch_angle() {
		return pitch_angle;
	}

	public void setPitch_angle(float pitch_angle) {
		this.pitch_angle = pitch_angle;
	}

	public float getRoll_angle() {
		return roll_angle;
	}

	public void setRoll_angle(float roll_angle) {
		this.roll_angle = roll_angle;
	}

	public int getXpos() {
		return xpos;
	}

	public void setXpos(int xpos) {
		this.xpos = xpos;
	}

	public int getYpos() {
		return ypos;
	}

	public void setYpos(int ypos) {
		this.ypos = ypos;
	}

	public float getAzimuth_angle() {
		return azimuth_angle;
	}

	public void setAzimuth_angle(float azimuth_angle) {
		this.azimuth_angle = azimuth_angle;
	}

}

[XML]<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:eek:rientation="vertical">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Testtext" />

<org.phobos.kompass.Panel
android:id="@+id/panel1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />


</LinearLayout>[/XML]
 

schlingel

Gesperrter Benutzer
Der Code sieht so aus als müsste er funktionieren. Wie's so ist mit Code tut er das aber meistens nicht oder nicht so wie wir das wollen.


Also bleibt dir wohl nichts anderes übrig als dich mal reinzudebuggen wenn die View am Bildschirm sichtbar ist aber sich nicht mehr verändert.
1. Wird onSensorChange aufgerufen? (Das ist ja leicht anhand der Text-Ausgabe nachzuvollziehen.)
2. Wird onDraw aufgerufen? Log.d-Ausgabe einbauen und checken. Wenn ja: Ändern sich die Parameter? Wenn nein: Funktioniert es mit einer noch einfacheren View?

Ein paar Anmerkungen hab ich so noch:
- Im onDraw schlafen gehen ist eine sehr schlechte Idee. Siehe auch meine Antwort hier.
- In Java herrscht der CamelCase also sollten Methodennamen nicht eine Mischform aus der üblichen _-Benennung aus C++ und dem CamelCase von Java sein. getPitchAngle statt getPitch_angle etc. sollte also verwendet werden. (Tut aber hier nichts zur Sache.)
 

phobos

Mitglied
Erst mal vielen Dank für deine Tips. Leider bin ich trotzdem noch nicht weiter gekommen.
Bei Programmstart wird onDraw() einmal aufgerufen. Danach nur noch onSensorChanged() und invalidate() abwechselnd. Hab herausgefunden dass während invalidate() eine Methode namens skipInvalidate() aufgerufen wird. Leider weiss ich nicht warum. Gibts ne Möglichkeit sich den Code von invalidate() irgendwo anzusehen? Ich werd jetzt nochmal ne einfache View schreiben und testen obs damit funktioniert. Aber falls ja, wie bringt mich das dann weiter?
 

schlingel

Gesperrter Benutzer
skipInvalidate, entgegengesetzt ihres Namens, prüft nur ob überhaupt gezeichnet werden soll. Die Methode wird also immer aufgerufen, siehe auch hier (Zeile 10122)

Allerdings habe ich auf Stackoverflow einen Post mit einem ähnlichen Problem gefunden. Vielleicht probierst du das einmal:
1. HW-Acceleration deaktivieren im Manifest und probieren ob es das ist.
2. Eine zweite View auch per invalidate anstoßen (z.B. die TextView)
 

phobos

Mitglied
Habs mit dieser View getestet, wird auch nicht aufgerufen. Wird wieder invalidateSkip() aufgerufen.
Java:
package org.phobos.kompass;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;

public class TestPanel extends View {

	public TestPanel(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	
	public void onDraw(Canvas canvas) {
		canvas.drawColor(Color.BLUE);
		
	}

}

Edit: Hab deinen neuen Beitrag noch nicht gelesen. Werd das mal ausprobieren. Danke
 

phobos

Mitglied
Wenn ich HW-Beschleunigung ausschalten will bekomm ich den Fehler:
Code:
error: No resource identifier found for attribute 'hardwareAccelerated' in package 'android'	AndroidManifest.xml	/kompass	line 9	Android AAPT Problem
Liegt wohl an
[XML] <uses-sdk android:minSdkVersion="8" />[/XML]
dh aber doch das dies nicht das Problem sein sollte oder? Hab am Telefon nochmal nachgesehen da is GPU-Rendering erzwingen auch auf aus.

Edit: Wenn ich
Code:
textFenster.invalidate();
einfüge wird onDraw() gar nicht aufgerufen. Nichtmal bei Programmstart. Ich verstehs einfach nicht :(
edit2: Ka was grade los war, jetzt sind wir jedenfalls wieder beim alten Stand. Die TextView wird aktualisiert, die andere nur einmal bei Programmstart, trotz des zweiten invalidate()
 
Zuletzt bearbeitet:

phobos

Mitglied
Kann es sein dass ich irgendwie 2 verschiedene Instanzen der Panel Klasse erzeuge und einfach auf die falsche zugegriffen wird? Ist denn das im main.xml angegebene Panel welches in
Java:
setContentView(R.layout.main);
gesetzt wird und das durch
Java:
mPanel = new Panel(this, attrs);
erzeugte das selbe Objekt? Irgendwie versteh ich die zusammenhänge da nicht ganz. Was passiert denn genau während setContentView()?
Wenn ich allerdings sowas wie
Java:
mPanel= (Panel) findViewById(R.id.panel1);
versuche ändert sich auch nichts. Wie komm ich denn an die durch setContentView erzeugte Instanz? Oder versteh ich da was komplett falsch?
 

schlingel

Gesperrter Benutzer
Mit findViewById. Wenn du new verwendest erzeugst du eine neue Referenz.

Das habe ich ganz überlesen. Du musst auf jeden Fall findViewById verwenden, ansonsten ist die View nicht sichtbar und das Zeichnen wird wirklich immer übersprungen.
 

phobos

Mitglied
Daaaanke :toll:

Endlich funktionierts wieder.
Nochmal kurz zu dem sleep, soll ich das dann unter onSensorChanged() machen oder soll ichs einfach ganz weg lassen? Richtig wärs wohl eine eigene Klasse/Thread zu machen die die Sensor Events entgegennimmt und da drin zu pausieren, oder? Aber von Threads hab ich noch gar keine Ahnung.
 

schlingel

Gesperrter Benutzer
@Sleep

Überlege dir kurz einmal die Architektur: Das sleep benötigst du für polling-Umgebungen also wo du aktiv nachfragen musst ob der Sensor etwas neues für dich hat. Dort macht es Sinn, dass du nicht ständig an den Systemressourcen saugst obwohl ein Update im Abstand von 5ms sinnlos ist. Dort würdest du das ganze in einen Thread auslagern und den schlafen lassen.

In deinem Fall passiert aber etwas anderes: Das lauern auf Updates erledigt das System. Du bekommst nur Benachrichtigungen wenn sich etwas geändert hat. Du reagierst sofort darauf und zeigst es an. Warum hier etwas verzögern?

Lass das ganze Schlafen weg.
 

phobos

Mitglied
ok, danke. Dh wenn ich Akku sparen will sollte ich das System dazu bewegen weniger oft zu prüfen ob sich die Sensoren geändert haben. Ich hab rausgefunden das ich dort:
Java:
		mSensorManager.registerListener(this, mOrientation,
				SensorManager.SENSOR_DELAY_NORMAL);
beim letzten Parameter auch eine Verzögerung in ms angeben kann, damit onSensorChanged() nicht dauernd aufgerufen wird.
 

schlingel

Gesperrter Benutzer
Darüber würde ich mir bei der App keine Sorgen machen. Wenn du zeitnah reagieren willst, belass es so. Wenn dir der Akku Sorgen macht, bau ein, dass die Activity per finish() beendet wird wenn der Benutzer die back-Taste drückt.

Denn wenn man die Activity gerade anzeigt wird es ja interessant sein, dass sich das verändert. Nur wenn's im Hintergrund ist, ist's ein "Problem". (Auch nicht wirklich)
 

phobos

Mitglied
Wo füge ich das finish() ein wenn ich möchte das die Activity beendet wird sobald sie nicht mehr im Vordergrund ist also sowohl bei drücken der Home Taste als auch der Back Taste? Bei onPause()?
 

mjdv

Bekanntes Mitglied
Eher bei onStop.

Ich würde aber eher gleich in onStop den Sensor wieder verwerfen, dann kannst dir das mit dem finish ganz sparen ;)
 

phobos

Mitglied
Ich hab jetzt nochmal ein wenig über den Activity Lifecycle nachgelesen. Ist es nicht so dass eigentlich vor onStop immer onPause aufgerufen wird. Dh der Sensor Listener sowieso wieder freigegeben wird. Oder fehlt da noch was? Muss ich dem SensorManager auch noch sagen dass ich ihn nicht mehr brauche?
Wenn ja, wie mache ich das?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
W Volly onErrorResponse trotz Erfolg Android & Cross-Platform Mobile Apps 3
S Umlaute werden trotz UTF-8 nicht angezeigt? Android & Cross-Platform Mobile Apps 6
S IF Anweisung zeigt Fehler trotz richtiger Eingabe? Android & Cross-Platform Mobile Apps 7
K Grafik Tablerow, Button erstreckt sich in der gesamten Breite trotz Beschrenkung durch (max)width Android & Cross-Platform Mobile Apps 2
G Check Button ist unchecked trotz setChecked(true) Android & Cross-Platform Mobile Apps 6
G trotz padding all around kein padding unten Android & Cross-Platform Mobile Apps 2
G trotz Android 4.1 erscheint option menu statt action bar Android & Cross-Platform Mobile Apps 5
W Reward Ads AdMob wird nicht ausgeliefert. Android & Cross-Platform Mobile Apps 9
J Spinner wird nicht aktualisiert Android & Cross-Platform Mobile Apps 6
Naxon89 Duplicate class kotlin - und dies ohne das es angewendet wird Android & Cross-Platform Mobile Apps 1
ImageView wird nicht angezeigt Android & Cross-Platform Mobile Apps 4
W Bildschirm Nutzung Überwachen der App Nutzer ink. was angeklickt wird Android & Cross-Platform Mobile Apps 35
N XY-Plottet keine Daten obwohl Funktion ausgeführt wird Android & Cross-Platform Mobile Apps 4
K Null-Pointer-Exception in ListView - wird über Datenbank gefüllt Android & Cross-Platform Mobile Apps 1
R Android Do not disturb: Sound wird nicht abgespielt Android & Cross-Platform Mobile Apps 2
O Google Admob Ad wird nicht geladen und App stürzt ab Android & Cross-Platform Mobile Apps 1
M Paper DB wird in Android Studio nicht erkannt Android & Cross-Platform Mobile Apps 7
R Audio wird nur 1 Mal abgespielt Android & Cross-Platform Mobile Apps 2
A GraphView => X- und Y-Achse wird nicht angezeigt Android & Cross-Platform Mobile Apps 5
A jpg wird im Android Studio nicht akzeptiert Android & Cross-Platform Mobile Apps 3
Arif Android Radiobutton wird nicht deaktiviert Android & Cross-Platform Mobile Apps 1
Arif Android Canvas wird nicht gezeichnet? Android & Cross-Platform Mobile Apps 0
J Notification wird nicht angezeigt wenn App nicht offen ist. Android & Cross-Platform Mobile Apps 6
M TypedArray-Resource wird falsch geladen Android & Cross-Platform Mobile Apps 7
W Preview wird nicht korrekt angezeigt Android & Cross-Platform Mobile Apps 0
B Profilpic wird nach anmeldung nicht angezeigt. Android & Cross-Platform Mobile Apps 2
K Methode wird nicht gefunden Android & Cross-Platform Mobile Apps 1
J Kamera - Foto wird nicht gespeichert Android & Cross-Platform Mobile Apps 2
V Android Wird mein Vorhaben funktionieren? (Apk Datei decompilieren, bearbeiten, compilieren) Android & Cross-Platform Mobile Apps 2
G App wird nach Installation auf Smartphone beendet Android & Cross-Platform Mobile Apps 1
L Dialog anzeigen wenn auf Button gedrückt wird. Android & Cross-Platform Mobile Apps 4
S Android neue Version des Programms wird nicht in Emulator geladen Android & Cross-Platform Mobile Apps 1
O Android Switch Widget wird nicht angezeigt Android & Cross-Platform Mobile Apps 1
M Android ListView wird nicht dargestellt Android & Cross-Platform Mobile Apps 2
N PriceScannerApp: warum wird nach dem Scannen Display gleich schwarz? Android & Cross-Platform Mobile Apps 4
P Herausfinden, welches Fragment gerade angezeigt wird. Android & Cross-Platform Mobile Apps 1
M Android Nur erste Zeile wird vom Server empfangen Android & Cross-Platform Mobile Apps 0
A App wird bei start des Timers beendet Android & Cross-Platform Mobile Apps 1
A Wieso wird die App beendet ??? Android & Cross-Platform Mobile Apps 2
B Alle Daten gehen verloren, wenn die Displaysperre aktiviert wird? Android & Cross-Platform Mobile Apps 21
W XML Layout: wann wird geladen? Android & Cross-Platform Mobile Apps 10
K Android Temperaturconverter, R.id.element wird nicht gefunden Android & Cross-Platform Mobile Apps 20
A onDraw wird nicht aufgerufen Android & Cross-Platform Mobile Apps 14
A Android Dialog wird nicht sofort angezeigt Android & Cross-Platform Mobile Apps 12
W ImageView wird nicht angezeigt Android & Cross-Platform Mobile Apps 19
T Android: ListView-Adapter: Adapter wird ständig aufgerufen Android & Cross-Platform Mobile Apps 2
F Android Datenbank upgrade wird nicht durchgeführt Android & Cross-Platform Mobile Apps 2
F Android R.raw wird nicht gefunden Android & Cross-Platform Mobile Apps 5
P ID wird nicht erzeugt Android & Cross-Platform Mobile Apps 2
C Problem Device/Emulator wird nicht erkannt Android & Cross-Platform Mobile Apps 3
R Zeichen-Codierung in (SMS) TextMessage, "_" wird § Android & Cross-Platform Mobile Apps 2

Ähnliche Java Themen

Neue Themen


Oben