Tuesday, November 11, 2014

BitTorrent Sync and how to Root a modern HTC One M8

Background


I just have discovered BitTorrent Sync. Now I can sync my carefully managed collection of music from my desktop PC with my work PC with my MacBook Pro with my Android phone. There are no fees and no bandwith or storage limits. Great!

Unfortunately since Android 4.4.2, access to the external SD card has been restricted. Now BT Sync is only allowed to write to /Android/data/com.bittorrent.sync on the external SD card.

The Android media scanner does not scan this folder and regular music players (like the stock Android music player and Google Play Music) will therefore not know about music in this folder.

You can play your music with a free app called Music Folder Player to work around this. But I wanted to use Google Play Music because it integrates with Google Voice Search and my Android Wear watch.


Solution: Root the phone so BT Sync can write to any folder it likes on the external SD card


Rooting an Android phone lets you run commands as the user "root".  The root user has read-write access to the system config files and can remove the restrictions on the external SD card.

Rooting your phone could theoretically go wrong and render your phone useless.  You proceed at your own risk!

Rooting a phone is generally a different procedure for each type of phone.  Here's my scenario:
  • Country of residence: UK
  • Network: Three
  • Handset: HTC One M8
  • Purchased: Aug-2014
  • OS: Android 4.4.4 (customised by Three)


Steps I took for my phone

  1. Root the phone using this guide.  Note that this step will wipe everything off the phone.
  2. Maybe optional for you. I couldn't save changes to the system config file because they are held in NAND memory and NAND memory is protected S-ON mode. So disable S-ON (i.e. gain S-OFF) by following this firewater guide.
  3. The firewater method didn't work for me. This is presumably because my modern HTC One M8 had an update in place which prevented the firewater hack. So I side-loaded and ran the Sunshine APK. Sunshine informed me that my device is eligable and prompted me to pay $25 using PayPal.
  4. Now I can make changes to my system files, so I ran SDFix which makes a tiny change to /etc/permissions/platform.xml which grants read-write access to the external SD file.
  5. Reboot the phone to apply the changes made to platform.xml

Now BitTorrent Sync does not complain when I point it to "SD card/Music". The Android media scanner watches this folder, so all the regular music players will play music from here. Hurrah!



Keywords: British UK HTC One M8 Three Google Play Music mp3 BitTorrent Sync /Android/data/com.bittorrent.sync Error message Don't Have Permissions To Write To Selected Folder

Thursday, March 15, 2012

Selenium 2 / JUnit 4 Test Case Example

I've had trouble finding one single comprehensive example of a Selenium 2.2 / JUnit 4.1 test case in the web. I've pieced together info from lots of different places to form such an example.

You will need the jar files from selenium-java-2.20.0.zip and junit-4.10.jar in order to run the example.


import java.util.NoSuchElementException;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;


public class SeleniumTestCase
{
private static final int TIMEOUT_IN_SECONDS = 30;
private WebDriver driver;


@Before
public void startWebDriver()
{
driver = new FirefoxDriver();
}


@Test
public void test()
{
// Open home page
driver.get("http://adambuckley.net");
Assert.assertTrue(isTextPresent(driver, "Adam Buckley"));

// Click link
driver.findElement(By.linkText("Academic Research")).click();

/*
* Wait for the page to finish downloading. In this simple case, this
* line isn't necessary because the WebDriver will block until the page
* has finished downloading. However, in other cases, the WebDriver
* won't block and it's up to the calling code to verify that the new
* page has been loaded.
*/
waitForElementPresent(driver, By.linkText("Distributed Multimedia Sequencing Using Java & CORBA"));

Assert.assertTrue(isTextPresent(driver, "Distributed Multimedia Sequencing Using Java & CORBA"));
}


@After
public void closeSession()
{
driver.close();
}


/**
* Waits until the specified element is present in the web page. This method
* is used in situations where Selenium does not block until a page is
* completely downloaded.
* <p>
* From the <a href="http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/WebElement.html#click%28%29">Selenium documentation</a>:
* If click() causes a new page to be loaded via an event or is done by
* sending a native event (which is a common case on Firefox, IE on Windows)
* then the method will *not* wait for it to be loaded and the caller should
* verify that a new page has been loaded.
*
* @param driver the active WebDriver
* @param by the element locator
* @throws org.openqa.selenium.TimeoutException if the element is not
* present within the page, or if the page does not download within
* TIMEOUT_IN_SECONDS
*/
private static void waitForElementPresent(final WebDriver driver, final By by)
{
new WebDriverWait(driver, TIMEOUT_IN_SECONDS).until(new ExpectedCondition()
{
@Override
public WebElement apply(final WebDriver d)
{
return d.findElement(by);
}
});
}


/**
* Searches for a String. This method is a substitute for the Selenium 1
* method 'verifyTextPresent'
*
* @param driver the active WebDriver
* @param searchStr a String to locate in the downloaded page
* @return true if searchStr was found in the downloaded page, false
* otherwise
*/
private static boolean isTextPresent(final WebDriver driver, final String searchStr)
{
try
{
driver.findElement(By.xpath("//*[contains(.,'" + searchStr + "')]"));
return true;
}
catch(final NoSuchElementException e)
{
return false;
}
}
}

Monday, February 13, 2012

XML-RPC WordPress client in Java

This code is an XML-RPC WordPress client written in Java. Note that you must first enable XML-RPC on your WordPress site which is under Settings > Write > Remote Publishing. Note also that you require xmlrpc-client-3.1.3.jar, xmlrpc-common-3.1.3.jar and ws-commons-util-1.0.2.jar on your classpath. These jar files can be found in the Apache XML-RPC distributable which is available in the mvnrepository if the Apache mirrors are unavailable. The WordPress website shows the full list of methods available.

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;


public class WordPressClient
{
 private static final String USERNAME = "username";
 private static final String PASSWORD = "password";
 private static final int BLOG_ID = 1;
 private static final String URL = "http://example.com/xmlrpc.php";


 public static void main(String[] args) throws Exception
 {
  System.out.println("Connecting to: " + URL);

  final XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
  config.setServerURL(new URL(URL));

  final XmlRpcClient client = new XmlRpcClient();
  client.setConfig(config);

  final Hashtable content = new Hashtable();
  content.put("wp_page_parent_id", 11);
  content.put("title", "Page Title");
  content.put("description", "Description goes here. You can use <b>some HTML markup</b>.");
  final boolean publish = true;

  final Object[] params = new Object[] { BLOG_ID, USERNAME, PASSWORD, content, publish };
  final Object result = client.execute("wp.newPage", params);
  final int pageId = Integer.parseInt(result.toString());

  System.out.println("Successful! New page ID is " + pageId);
 }
}

Tuesday, July 12, 2011

iTunes Freezes When I Plug my iPhone In

Whenever I plug my iPhone into my PC over USB, iTunes freezes. It instantly unfreezes when I unplug my iPhone. This may have started happening following an iTunes update in April-2011. It may indeed be caused by this update or it may be co-incidence and the fault may be electronic, related to my overclocked system.

iTunes also freezes under any other user account on the same machine. Even if iTunes has frozen, the iPhone is available under 'My Computer' and gives me access to digital photos I took with the iPhone.

The iPhone works fine with any other machine and doesn't cause iTunes to freeze.

I have installed all Apple updates and I've exhaustively followed this guide: iTunes: May become unresponsive when connecting iPhone, iPad, or iPod touch.

My system: Windows 7 64-bit; Intel Core i7 @ 2.67GHz


My Solution
  1. Plug in your iPhone and allow iTunes to freeze
  2. Click Start > Control Panel > Administrative Tools > Services
  3. Right-click the service called "Apple Mobile Device" and choose "Restart"
  4. iTunes will become responsive for a fraction of a second, but may then freeze again
  5. Repeat step 3 until iTunes becomes responsive and your iPhone appears under "DEVICES" in the left-hand panel.
  6. I normally have to restart the mobile device service 2 or 3 times before iTunes becomes responsive again

Update 25-Jul-2011

It would seem that the iTunes 10.4.0.80 update has resolved this problem for me.