Zum Inhalt springen

Autor: Dennis Wilmsmannn

Android 5.0.2 für das Nexus 7 (2012) wird verteilt

Mein Nexus 7 (2012) hat vorgestern das OTA Update für Android Lollipop 5.0.2 bekommen:

Screenshot_2015-01-23-14-55-27

 

Das Update hat dann ewig gedauert (über 1 Stunde) und das Tablet fühlt sich nun träger an als vorher. Kann aber auch rein subjektiv sein. Was mir allerdings gefällt, ist das neue Design und das auf dem gesperrten Homescreen Meldungen von Apps angezeigt werden können, z.B. wenn neue Nachrichten von WhatsApp & Co. eingetroffen sind.

KeeFox kann keine Verbindung zu KeePass herstellen

Ich habe quasi nach jedem Update vom KeeFox Addon oder Firefox selbst das Problem, dass KeeFox keine Verbindung mehr zu KeePass herstellen kann. Auch die Hilfe Seite von KeeFox hat mir nicht geholfen. Nach mehrfachen Neustarts von Firefox und/oder KeePass gings dann irgendwann wieder, die genaue Ursache hatte ich bisher aber nicht herausgefunden. Ob das hier jetzt die endgültige Lösung ist, weiß ich allerdings auch noch nicht.

KeeFox speichert im Passwortmanager von Firefox ein Token ab, was für die Authentifizierung zwischen Firefox und KeePass benutzt wird. Wenn man dieses Token löscht und Firefox dann neu startet, wird ein neues Token erstellt und schon klappt die Verbindung wieder.

Im Passwortmanager  muss in meinem Fall die oberste Zeile entfernt werden:

keefox_1

Und jetzt nur noch das neue Token speichern:

keefox_2

keefox_3

 

In KeePass sollte nun die neue Verbindung auch in den KeePassRPC (KeeFox) Options angezeigt werden:

keefox_4

 

 

Bluetooth Maus verliert die Verbindung

Meine Bluetooth Maus (ja, ich weiß, eine eher billige Version) verliert unregelmäßig die Verbindung zum Notebook. Neue Batterien und Treiber haben leider nix gebracht. Im Endeffekt lag es an den Energiespareinstellungen für die USB Anschlüsse, denn scheinbar ist der Bluetooth Empfänger im Notebook intern über USB angebunden, was wohl keine Besonderheit ist. Nachdem ich die Einstellungen für selektives Energiesparen für USB deaktiviert hatte, war auch das Problem verschwunden:

Selektives_USB-Energiesparen

WLAN Reichweite erweitern

Wenn man einen zweiten WLAN Accesspoint oder auch WLAN Router ins bestehende Netzwerk hängt und einfach den Namen und das Passwort vom bereits aktiven WLAN übernimmt, kann man die Reichweite des WLANs sehr einfach vergrößern, ohne das man bei den Endgeräten (Notebook, Smartphone usw.) ein neues WLAN einrichten muss.

Überprüfen kann man das dann z.B. mit der App Wifi Analyzer.

wifi_range

Mein ursprüngliches WLAN ist das obere auf der Liste, das untere ist ein alter Netgear WLAN Router. Je nachdem, zu welchem der beiden der Empfang besser ist, verbindet sich das Smartphone passend. DHCP ist nur auf dem oberen Router aktiv, auf dem unteren deaktiviert, wie auch alle anderen „Zusatzfunktionen“.

Apache CXF Client mit Basic Authentication

Ein einfacher Apache CXF Client mit Basic Authentication lässt sich mit ein paar Zeilen Java Code umsetzen.

Via maven lassen wir uns aus einer WSDL Datei einen Client generieren:

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>2.7.4</version>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
                <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
                <wsdlOptions>
                    <wsdlOption>
                        <!-- hier eine valide WSDL Url angeben -->
                        <wsdl>https://www.denniswilmsmann.de/ws/soap/dummyservice?wsdl</wsdl>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Und die dazugehörige Implementierung mit Basic Authentication (leicht gekürzt):

import javax.xml.ws.BindingProvider;

public class Client {

  public static void main(String[] args) {
    MyWebServiceImpl ws = new MyWebServiceImpl();
    MyWebServiceService client = ws.getMyWebServiceImplPort();

    BindingProvider portBP = (BindingProvider) client;
    portBP.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "username");
    portBP.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");

    List<Result> results = client.getResult(true, 5.0, 1);

    System.out.println(results.size());
  }

}

WLAN über WLAN freigeben

Mit dem kleinen Tool MyPublicWiFi ist es möglich, unter Windows eine bestehende WLAN Verbindung für andere Geräte freizugeben. Das ist ganz praktisch, wenn man z.B. im Urlaub nur die Möglichkeit hat, mit einem Gerät aufs WLAN zuzugreifen, wie in vielen Hotels oder Ferienparks. Trotzdem möchte man aber neben dem Notebook auch mit dem Handy ins Internet gehen können.

Installation und Einrichtung klappen problemlos, das Tool selbst muss aber mit Admin-Rechten gestartet werden:

share_wifi_1

 

 

Und so sieht das dann auf meinem Moto G aus –  Mein normales WLAN ist Mirkwood und das neue, von meinem Notebook freigegebene ist MyPublicWifi:
share_wifi_2 share_wifi_3 share_wifi_4

 

Installation und Konfiguration haben keine 5 Minuten gedauert. 🙂

Random File Picker

Mit diesem paar Zeilen Code ist es mit Java 7 möglich, zufällig Dateien aus einer Ordnerstruktur zu kopieren, z.B. um schnell mal 100 mp3 Dateien aus der Sammlung auf eine CD oder einen USB Stick zu schieben, ohne selbst bei der Auswahl Hand kreativ werden zu müssen.

Hier gibts den Sourcecode und ein fertiges JAR File zum Download: RandomFilePicker

/*
* Created on 30.08.2014
*/
package de.denniswilmsmann.rfp;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;

/*
* $Log: $
*/

public class RandomFilePicker {

	private final static List<File> files = new ArrayList<File>();

	public static void main(String[] args) {

		if (args == null || args.length < 4) {
			System.out
					.println("run with java -jar RandomFilePicker.jar <Source Folder> <Destination Folder> <Recursive y/n> <Number of Files>");
			System.out
					.println("run with java -jar RandomFilePicker.jar D:\\MyMusicArchive D:\\RandomMusic y 100");
			return;
		}

		File sourceFolder = new File(args[0]);

		if (!sourceFolder.isDirectory()) {
			System.out.println(args[0] + " is not a folder");
			return;
		}

		File destFolder = new File(args[1]);

		if (!sourceFolder.isDirectory()) {
			System.out.println(args[1] + " is not a folder");
			return;
		}

		boolean recursive = false;
		if (args[2].equalsIgnoreCase("y")) {
			recursive = true;
		}

		int numberOfFiles = Integer.parseInt(args[3]);

		parseFolder(sourceFolder, recursive);

		if (files.size() < numberOfFiles) {
			System.out
					.println("not enough files found, please reduce <Number of Files>");
		} else {
			Set<File> selectedFiles = new HashSet<File>();
			Random generator = new Random();
			while (selectedFiles.size() < numberOfFiles) {
				int i = generator.nextInt(files.size());
				selectedFiles.add(files.get(i));
			}
			for (File f : selectedFiles) {
				File out = new File(destFolder.getAbsolutePath()
						+ File.separator + f.getName());
				try {
					Files.copy(f.toPath(), out.toPath());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	private static void parseFolder(File folder, boolean recursive) {
		for (File f : folder.listFiles()) {
			if (f.isFile()) {
				addFile(f);
			} else if (f.isDirectory() && recursive) {
				parseFolder(f, recursive);
			}
		}
	}

	private static void addFile(File f) {
		// System.out.println(files.size() + 1 + ": " + f.getAbsolutePath());
		files.add(f);
	}
}

Chrome zeigt unter Android weiße bzw. leere Seiten

Seit den letzten ein oder zwei Updates hat Chrome unter Android die dumme Angewohnheit, ab und an weiße bzw. leere Seiten anzuzeigen. Dabei ist es egal, welche Seiten man versucht aufzurufen, denn auch Seiten von Google selbst sind betroffen.

So sieht die leere Seite aus:

Und so sollte die Seiten eigentlich aussehen:

Den Cache zu leeren oder sonst irgendwie an den Einstellungen rumzuspielen, hat bei mir keinen Erfolg gebracht. Aber scheinbar bin ich auch nicht ganz alleine mit diesen Problem, wenn man mal einen Blick auch die Chrome Seite im Play Store wirft:

Kleines Update vom 06.08.2014: Das Problem ist als Bug scheinbar schon seit Februar 2014 bekannt: Issue 342190: OOM conditions killing foreground render process
Scheinbar steht auch ein möglicher Bugfix für die Beta Version in den Startlöchern: https://code.google.com/p/chromium/issues/detail?id=399521#c2

Update vom 25.08.2014: Das letzte Update von Chrome hat das Problem behoben. 🙂

Probleme mit dem Moto G nach dem Update auf Android 4.4.4

Seit einiger Zeit verteilt Motorola das Update auf Android 4.4.4 für das Moto G und auch auf meinem Moto G (alte Version mit 16 GB Speicher) ist es mittlerweile angekommen. Es gibt jetzt ja auch eine Version mit 8 GB Speicher, einem Micro SD Slot und 4G (also LTE), zu der ich wegen der Micro SD nun greifen würden.

Moto G - Android 4.4.4

Aber zurück zum Update: Einen Verbesserung der Leistung oder Laufzeit kann ich nicht feststellen, habe ich aber auch nicht erwartet. Allerdings beenden sich nun deutlich schneller Apps, als vor dem Update. Vor dem Update konnte ich z.B. Musik hören, mit Feedly diverse RSS Feeds browsen und die Artikel dann per Chrome lesen. Nun beendet sich Feedly ab und an, wenn ich den Artikel in Chrome lese. Ist irgendwie ärgerlich, denn dadurch lande ich bei Feedly immer wieder auf dem Home Screen und nicht mehr da, wo ich vorher war.  Kann natürlich auch an Feedly, Chrome oder einer sonstigen App liegen.

Fotos mit Zeitstempel umbenennen

Mit den folgenden paar Zeilen Java Code lassen sich Fotos bequemen umbenennen, d.h. der Dateiname wird noch mit dem Zeitstempel aus den Exif Daten ergänzt. Möglich macht das das Framework metadata-extractor.

/*
 * Created on 28.06.2014
 */
package de.denniswilmsmann.renamephotos;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;

/*
 * $Log: $
 */
public class RenamePhotos {

  private final DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG);
  private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmmss");

  public static void main(String[] args) {
    File folder = new File("D:\\PhotosToRename\\");

    RenamePhotos ex = new RenamePhotos();
    ex.parse(folder);
  }

  private void parse(File f) {
    if (f.isDirectory()) {
      parseDirectory(f);
    } else {
      parseFile(f);
    }
  }

  private void parseDirectory(File f) {
    for (File file : f.listFiles()) {
      if (file.isDirectory()) {
        parseDirectory(file);
      } else {
        parseFile(file);
      }
    }
  }

  private void parseFile(File f) {
    try {
      if (f.isFile() && isRenameRequired(f)) {
        Metadata metadata = ImageMetadataReader.readMetadata(f);
        ExifSubIFDDirectory directory = metadata.getDirectory(ExifSubIFDDirectory.class);
        Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);

        String newName = sdf.format(date) + "_" + f.getName();
        System.out.println(f.getName() + " -> " + newName);

        f.renameTo(new File(f.getParent() + "\\" + newName));
      } else {
        System.out.println("skip " + f.getAbsolutePath());
      }
    } catch (ImageProcessingException e) {
      System.out.println("error parsing " + f.getAbsolutePath());
    } catch (IOException e) {
      System.out.println("error parsing " + f.getAbsolutePath());
    } catch (NullPointerException e) {
      System.out.println("error parsing " + f.getAbsolutePath());
    }
  }

  private boolean isRenameRequired(File f) {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < f.getName().length(); i++) {
      sb.append(f.getName().charAt(i));
      try {
        sdf.parse(sb.toString());
        return false;
      } catch (ParseException e) {
        // ignore
      }

    }
    return true;
  }
}

Und dazu noch die passsende pom.xml, damit die Dependencies einfach via maven geladen werden können:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>RenamePhotos</groupId>
	<artifactId>RenamePhotos</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>com.drewnoakes</groupId>
			<artifactId>metadata-extractor</artifactId>
			<version>2.6.2</version>
		</dependency>
	</dependencies>
</project>

Hier die Dateien vorher:
renamephotos1

Und nachher:
renamephotos2

Die Ausgabe auf der Konsole sieht dazu so aus:

CIMG2773.JPG -> 2012-02-23_172829_CIMG2773.JPG
CIMG2774.JPG -> 2012-02-23_172842_CIMG2774.JPG
CIMG2775.JPG -> 2012-02-23_172847_CIMG2775.JPG
CIMG2776.JPG -> 2012-02-23_172853_CIMG2776.JPG
CIMG2777.JPG -> 2012-02-23_184732_CIMG2777.JPG
CIMG2778.JPG -> 2012-02-23_184746_CIMG2778.JPG
CIMG2779.JPG -> 2012-02-23_184752_CIMG2779.JPG
CIMG2780.JPG -> 2012-02-23_211635_CIMG2780.JPG
CIMG2781.JPG -> 2012-02-23_211646_CIMG2781.JPG
CIMG2782.JPG -> 2012-02-23_211655_CIMG2782.JPG
CIMG2783.JPG -> 2012-02-23_211714_CIMG2783.JPG
CIMG2784.JPG -> 2012-02-23_211724_CIMG2784.JPG
CIMG2785.JPG -> 2012-02-23_211735_CIMG2785.JPG
CIMG2786.JPG -> 2012-02-23_211745_CIMG2786.JPG
CIMG2787.JPG -> 2012-02-23_211801_CIMG2787.JPG
CIMG2788.JPG -> 2012-02-23_211810_CIMG2788.JPG
CIMG2789.JPG -> 2012-02-23_211822_CIMG2789.JPG
error parsing D:\PhotosToRename\desktop.ini

Der Code Style für den eclipse Java Formatter stammt von Google: https://google-styleguide.googlecode.com/svn/trunk/eclipse-java-google-style.xml

Ach ja, es gibt natürlich auch diverse kleine Tools, die das auch alles können, z.B. ExifRenamer für Mac OS oder dieses Tool für Windows.