Beiträge von block_

    Es kann sein, dass ich hier jetzt bisschen was falsches dazu erzähle, aber es war auch schon, wie gesagt, lange her, dass ich das gemacht habe :P
    Also, da der DefaultHTTPClient nicht mit HTTPS umgehen konnte, hab ich eine neue Klasse erstellt, die von DefaultHTTPClient ableitet und so implementiert, dass dieser auch mit HTTPS klar kommt.


    SecureHTTPClient:


    In der newSslSocketFactory() wird dann der KeyStore geladen, welches von der KeyStoreHandler Klasse gemacht wird.
    KeyStoreHandler:


    Die Konstanten oben musst du dann jeweils noch anpassen.
    KEYSTORE_FILE_NAME ist einfach nur der Name der KeyStore Datei (was der name ja auch schon sagt :P). Ist eigentlich egal wie du die Datei nennst.
    KEYSTORE_PASSWORD ist für das Passwort für den KeyStore, da ein KeyStore ja immer mit Passwort gesichert sein muss.
    CERTIFICATE_ALIAS bin ich mir nicht ganz sicher, aber das steht beim Zertifikat immer dabei. Müsste der einfach Allgemeine Name (CN) sein.
    CERTIFICATE_URL ist die genaue Adresse zum Zertifikat auf dem Server. Das ist wichtig, da ja das Zertifikat runtergeladen und in den KeyStore gespeichert wird. (Frag mich jetzt nicht, wie ich an die Adresse gekommen bin, da müsste ich auch nochmal nachgucken :P)


    Näher gehe ich jetzt mal nicht auf den Code ein, dazu müsste ich mir auch kurz Zeit nehmen, aber das kriegst du bestimmt auch selber hin den zu verstehen. Viel Hokus-Pokus ist das nicht.


    Und so wird das Ganze dann benutzt:


    Ich hoffe ich hab nichts vergessen. Es ist vielleicht nicht optimal gelöst (siehe Exception-Handling usw.) und es ist auch nicht die einzige Lösung, aber sie hat funktioniert und das war die Hauptsache.


    block_

    Entweder die NetworkOnMainThreadException oder eine CertificateException (bin mir nicht sicher ob die so heißt). Ich vermute eher letzteres, da das Zertifikat nicht akzeptiert wurde (glaube die Meldung hieß auch so ähnlich: "Certificate not trusted"). Hab mich auch mal eine Weile damit beschäftigt, ist aber schon länger her. Wenn es das wirklich ist, kann ich meine Lösung dazu hier mal reinstellen.


    Achja, bei mir wird auch ein neuer KeyStore erstellt, wie im ersten Post schon angemerkt.


    block_

    Bei den ersten paar Fehlern vermute ich mal, dass damit TabFragment gemeint ist. TabFragment ist aus dem Beispiel von StackOverflow nur ein Platzhalter. Du musst da schon deine eigenen Fragmente einfügen (Der Inhalt von Tabs wird meist durch Fragmente dargestellt. Falls dir das nicht viel sagt, solltest du dir das am besten noch eben angucken). Aus dem Code aus deinem ersten Post würde ich sagen, dass da die BMIRechner, WHTRRechner und KalorienRechenr Klassen gemeint sind (solange sie eben als Fragmente implementiert wurden).
    Bei den letzten beiden bin ich mir nicht sicher. Für ActionBar eventuell den Import nicht eingefügt? Welche meldung gibt er bei setProviderId aus?


    block_

    Du benutzt hier die SherlockActivity und die hat keine Funktion getTabHost(). Die gibt es nur, wenn du von TabActivity ableitest, welches aber zu Standart Android gehört. Willst das mit ActionBarSherlock machen, musst du die Tabs über die Actionbar einfügen.
    Bei StackOverflow gibts ein gutes Beispiel dafür, wie man mit Tabs arbeitet.


    block_

    Hallo Leute,
    heute will ich euch ein Projekt von mir vorstellen, welches ich mit einem Kollegen zusammen entwickelt hab.
    Hauptziel dieser App ist es, zusammen mit mehreren Leuten gleichzeitig an einem Bild zu arbeiten. Alles was ihr dafür braucht ist eine WLAN-Verbindung zu einem Netzwerk und eure Kreativität!


    Das Ganze läuft in etwa so ab:
    Jemand erstellt einen neuen Raum (ähnlich wie man das aus dem Chat-Bereich kennt, verschiedene Chat-Räume usw.), legt dabei den Namen des Raumes und die Anzahl der Personen fest, die beitreten dürfen. Ist der Raum einmal erstellt, so können alle anderen diesen suchen und beitreten, solange sich diese ebenfalls im selben WLAN befinden. Anschließend können alle zusammen in Echtzeit drauf los malen.


    Ihr kennt bereits schon Apps, die die selbe Idee umgesetzt haben? Wir auch, jedoch waren wir nicht so wirklich begeistert von den meisten. Entweder war das ganze nicht sehr "live" oder ging nicht wirklich. Daher unser Versuch das ganze umzusetzen. Ob es uns gelungen ist, entscheidet natürlich auch Ihr.
    Gibt es Anregungen, Kritik oder Vorschläge, dann immer her damit. Wir hören uns alles gerne an, solange es sachlich argumentiert wird.


    Diese App gibt es in zwei Versionen: Einmal die Lite (kostenlos, aber mit Werbung) und die Pro (kleiner Preis, aber werbefrei + zusätzliche Funktionen).
    Hier noch einmal kurz die Funktionsübersicht zu beiden Versionen:
    Lite:

    • Erstellen eines Raumes mit Namen und Anzahl der Benutzer die beitreten dürfen
    • Suche des Raumes im Netzwerk. Beitritt entweder durch die automatische Suche oder das Eingeben einer IP-Adresse
    • Malen mit bis zu 3 Freunden - und das gleichzeitig
    • Verschiedene Werkzeige stehen zur Verfügung: Normale Pinsel, Weicher Pinsel, Relief, Überdecken, Radieren, Farbauswahl, Pinselgröße
    • Ansicht der Rauminformationen (Name, Admin, Adresse) mit allen verbundenen Benutzern
    • Speicherung des Bildes in der Galerie
    • Eigenen Namen für das Gerät angeben (Den Namen sehen alle in den Rauminformationen)


    Pro:

    • Alles was die Lite auch kann (siehe oben)
    • Malen bis zu 6 Freunden!
    • Raum durch ein Passwort schützen
    • Der Administrator hat in den Rauminformationen noch zusätzliche Funktionen für die einzelnen Benutzer: Kick + Rechteverwaltung (darf der Benutzer malen oder nicht)
    • Integrierte Chat (falls die anderen Personen sich in einem anderen Raum aufhält)
    • Zuschauer-Modus (eigene Mal funktionen deaktivieren, sodass nicht zufällig was gemalt werden kann, falls man dies nicht möchte)
    • Werbefrei!


    Wir wissen, dass es vom Design nicht sehr überragend ist, aber mehr konnten wir (bisher!) als reine Entwickler nicht rausbekommen :P Aber wir arbeiten daran.
    Wenn ihr euch fragt, warum zwei Versionen oder warum sollte ich für die Pro bezahlen, wenn nur ein paar Zusatzfunktionen implementiert wurden, dann können wir euch sagen, dass es erst der Anfang ist. Es kommen noch weitere, keine Sorge ;)
    Allerdings mussten wir feststellen das unsere bisherige Code-Basis nicht ganz optimal ist (da auch wir dabei erst noch viel lernen konnten, und man mit der Zeit ja auch besser wird), wird für die nächste Version erstmal einiges Code-technisch hübscher und (ich trau mich noch garnicht sowas zu sagen:P) professioneller ausgearbeitet, um einfacher neue Funktionen implementieren zu können, aber auch um die Usability für den Benutzer zu verbessern.


    Link für die Lite im Play-Store: DrawTogether Lite
    Link für die Pro im Play-Store: DrawTogether Pro
    (Die Bilder könnt ihr euch dort auch ansehen, daher hab ich die hier nicht extra hochladen wollen.)


    Getestet haben wir das bei uns in der FH und es lief soweit sehr gut. Solange man sich eben im selben WLAN befindet (und das Signal auch recht stark ist, wobei es auch läuft wenns mal nicht ganz so stark ist), funktioniert das auch, wenn die Personen in unterschiedlichen Gebäuden sitzen (Während einer Vorlesung zum Beispiel ... :P).


    block_

    Kleine Anmerkung zum Beitrag von Lucas:

    Code
    itemsCopy = allItems;


    Da wird die Referenz von allItems an itemsCopy zugewiesen. Somit zeigen beide auf die selbe (original) Liste.



    So wird eine (flache) Kopie erstellt.

    Code
    List<Song> allItems   = ...;
    [..]
    List<Song> itemsCopy = new ArrayList<Song>(allItems);


    Ansonsten stimme ich Lucas voll und ganz zu.


    block_

    Aber wie können die werte false sein? diese werte gebe ich doch über den thread? bei der deklaration habe ich zumindestens keine werte zugewiesen (siehe code).


    Du hast es nicht explizit zugewiesen, aber primitive Datentypen haben immer einen Standartwert. Bei boolean ist es false, bei int ist es 0, etc.. (Nicht-primitive Datentypen, bspw. String, haben als Standartwert immer null.)


    block_

    Ich meine in einem anderen Thread von dir gesehen zu haben, dass das bei dir wie folgt abläuft (Pseudocode)

    Code
    Thread erstellen;
     Thread starten;
    
    
     Abfrage (URL1.online() && URL2.online()) { tu was;}


    Falls es wirklich noch so aufgebaut ist (und das ist auch das, was ich aus deiner Beschreibung des Problems vermute), vergisst du das Konzept, welches hinter Threads steht. Ein Thread zu erstellen und abzuarbeiten kostet nunmal Zeit. D.h. während der Thread erstellt und abgearbeitet wird, läuft der UI-Thread immer noch fröhlich weiter (die onCreate()-Methode). Daher ist bei der Abfrage das boolean immer noch false, weil der Thread eben nicht schnell genug war diesen zu aktualisieren.


    block_

    Wo dran hängt es denn? Den Text aus dem EditText bekommst du mit editText.getText().toString(). Wie man in eine Datenbank speichert, kommt drauf an, welche Datenbank du haben willst. Die interne von Android? Eine externe auf einem Webserver? Mit bisschen googeln bekommt man für jedes der Punkte viele Informationen.


    block_

    Dein mainListView ist null. Das liegt daran, dass findViewById in dem Layout, dass du gesetzt hast (setContentView), keine View mit der ID R.id.mainListView hast. Diese ist nicht in der Activity_main.xml, sondern in der News.xml definiert. (findViewByID bezieht sich immer auf das Layout, dass du eben mit setContentView gesetzt hast.) Übernimm die ListView mit in die Activity_main.xml und der Fehler sollte weg sein.


    block_

    wäre es auch möglich, dass immer beim drücken eines buttons stets eine andere musik abgespielt wird? ich habe ja pro genre nur 3 musikstücke. es kam vor dass die gleiche mukke 3-4 mal hintereinander zufällig gewählt wurde. bei 3 musikstücken ist das sehr wahrscheinlich.


    Du könntest den jeweiligen Index des gerade abgespielten Liedes in ein HashSet speichern und nach jedem Welchsel prüfen, ob das neue ausgewählte Lied bzw. der Index des Liedes bereits in diesem HashSet vorhanden ist. Ist er das, wähle ein neues. Ist er das nicht, spiel die Musik ab und füge den dazugehörigen Index in den HashSet. Sind alle Lieder gespielt worden, leere den HashSet und fang wieder von vorne an.


    Für die anderen Fragen:
    Die Resourcen werden in Android als statische int Variablen gespeichert. Diese "komische Zahl" ist also ganz normal. Bei dem TextView gibt es verschiedene Methoden zum setzen des Textes. Da du eine Resourcen-ID übergibst (den int Wert), wird intern der eigentliche Wert zu der Resource ermittelt. In diesem Fall dein res/raw/rock_c.mp3. In der Log findet die Ermittlung jedoch nicht statt und der eigentliche int Wert wird ganz normal ausgegeben.
    Laut dem Blog-Eintrag hier gehen beide Möglichkeiten (ist zwar schon echt lange her der Eintrag, aber es scheint sich bis heute nicht viel geändert zu haben). Zwischen Package-Name und der Res-ID gehört jedoch noch ein "/", dann sollte das ebenfalls funktionieren. Ich hab es zwar nicht getestet, aber du könntest es ja einfach mal ausprobieren und gegebenenfalls Bescheid sagen, falls dem nicht so ist :)


    Hoffe das ist einigermaßen verständlich ausgedrückt.


    block_

    MediaPlayer.create(...) liefert bei dir null. Daher wird eine NPE geworfen, wenn du auf mp eine weitere Methode aufrufst. Der Fehler liegt wohl bei der Uri, weswegen der MediaPlayer keine gültige Datei findet und daher null zurückgibt.


    Laut Google muss eine Uri für die raw Resourcen so aufgebaut werden: "android.resource://[package]/[res id]". Beachte dabei, dass die res id auch wirklich die statische Resource sein muss und nicht wie bei dir als String. Mach aus aus dem String Array ein int Array

    Code
    int [] playlist_Black	= {R.raw.black_a, R.raw.black_b, R.raw.black_c};


    und baue anschließend deine Uri nach dem oben genannten Muster auf. Viel einfacher ist es jedoch ohne Uri. Es gibt eine MediaPlayer.create(Context, int) der du einfach die Resource-Id übergeben kannst.

    Code
    mp = MediaPlayer.create(getApplicationContext(), playlist_Black[r.nextInt(playlistBlack.length)]);


    Noch ein paar Anmerkungen zu dem restlichen Code:

    • Variablennamen werden nur in lower CamelCase bennant (ohne _ und dergleichen)
    • Du fragst zuerst in der if ob der MediaPlayer grade was abspielt. Erst in der else jedoch initialisierst du diesen aber erst. D.h. dir wird schon am Anfang eine NPE geworfen. Versuch das logischer aufzubauen. (Ist MediaPlayer =! null dann prüfe ob gespielt wird. Ist er null, dann erstelle diesen neu.)
    • Du hast in vielen Methoden immer ein und den selben Code. Lager diesen in eine weitere Methode aus. Das ehröht die Wartbarkeit und verhindert ständiges Copy&Paste bei Änderungen. Für sowas gibt es ein bekanntes Prinzipt: DRY. Don't repeat yourself!


    block_

    Naja, von den Objekten werden nur int variablen gespeichert, diese haben jedoch alle auch mindestens eine Bitmap zugeordnet. Vom serialisieren hab ich bisher noch nichts gehört, funktioniert sowas mit einer Bitmap denn auch? Werd mich am Abend dann mal über das Serialisieren schlau machen


    Bitmaps sind leider nicht serialisierbar. Diese werden auf einem anderen Weg persistent gespeichert. Die Bitmap nochmal zu speichern würde bei dir keinen Sinn haben, da, so wie ich den Code verstanden habe, durch die ID ein Bitmap aus den Resourcen bzw. Assets schon geladen wird. Habe jedoch übersehen, dass das Bitmap nach dem Laden sofort dem Objekt zugeordnet wird. Wenn du die Serialisierung ausporbieren möchtest, musst du wohl ein wenig deine Klassenstruktur verändern. Ob es dir das Wert ist, kann ich jetzt nicht sagen und du musst dich auch nicht zwingend an die Serialisierung halten ;) (Mehr Aufwand ist gewiss nicht meine Absicht für dein Ziel.)


    Dann sollte das Kopieren auch klappen. :)


    Da würde mich wundern. Das Speichern und Lesen funktionert ja. Und das Kopieren wurde auch nicht durch fehlende Rechte verhindert. Die Datei konnte ja kopiert werden, nur scheinen Teile davon danach nicht mehr vorhanden zu sein.
    Aber grundsätzlich gebe ich dir bei deiner Aussage recht!


    block_

    Wie hast du kopiert? Hast du irgendein Unterschied bei der Kopie feststellen können (Größe etc.)?


    Wenn das, wie du gesagt hast, Einlesen ohne Kopieren funktionert, sollte es wirklich nicht am Code liegen. Eine schönere Variante hab ich dennoch als Tipp.
    Wenn ich das richtig sehe, dann besteht ein GraphicObject nur aus int-Werten die du in eine Datei speicherst. Da int ein primitiver Datentyp ist, ist er auch serialisierbar. D.h. du kannst dem GraphicObject ein implements Serializable hinzufügen und dann samt der ganzen ArrayList (die auch serialisierbar ist) durch ein ObjectOutputStream/ObjectInputStream schreiben bzw. lesen. Geht meiner meinung nach viel schneller und man braucht nicht alles per Hand machen. Eventuell löst dies auch dein Kopie-Problem, glaube ich aber ehrlichgesagt auch nicht.


    Für die Dateiendung musst du soweit nichts weiter beachten. Es kommt halt immer drauf an wie man Speichert bzw. Einliest. Ansonsten ist die Dateiendung eher irrelevant. Für die Auswahl eines Standartporgramms musst du einen intent-filter definieren. Bei Stackoverflow gibt es dazu bereits schon was zum nachlesen.


    block_

    Mache das ebenfalls so wie UweApps. Wusste auch garnicht das es einen vorgefertigten Weg gibt. Sind mir aber als fauler Typ zu viele Klicks, die man machen muss :P Da bleibe ich lieber bei dem gewohnten.


    block_

    Das ich das auf beiden Seiten (Client/Server) ändern muss, dessen bin ich mir schon bewusst. Ich versuche halt einen möglichst guten Kompromiss zu finden, der das ganze übersichtlicher macht, aber auch das man an so wenig Stellen wie möglich Änderungen durchführen muss.
    Deine Kombination aus enum+int und switch würde mir bisher nicht viel bringen, da ich die Befehle als String brauche ( "server_tu_dies"). Allerdings könnte man den enum auch eine String Varaiable verpassen, wodurch aber die switch nicht mehr funktionieren würde (Strings in switch erst ab java7). Würde ich dann für jeden Befehl eine Klasse anlegen und dazu ein enum mit dem Namen der Klasse, könnte man das laden mit Reflection lösen und man hätte nur noch zwei Stellen die man ändern muss. Da es aber sowieso darauf hinaus läuft, an mehreren Stellen zu bearbeiten muss ich mir erst angucken, welche Methode einfacher und schneller zu handhaben ist.


    Dein Objektansatz ist zwar recht schön, doch verstößt er für mich gegen das Prinzip der Kapselung. Es sollten ja Daten und Logik getrennt sein.


    Wo siehst du hier eine Verletzung des dir genannten Prinzips? In meinen Augen ist das alles Logik.


    block_