Automatic uploads of Android apk files to Google Play

To save time you can automate the process of uploading new apk files to Google Play using tools like gradle-play-publisher or fastlane. The process is simple. First you have to create a Google Service account and download the created p12 file. In the Google Play console you have to configure the access for this account. … Continue reading “Automatic uploads of Android apk files to Google Play”

To save time you can automate the process of uploading new apk files to Google Play using tools like gradle-play-publisher or fastlane.

The process is simple. First you have to create a Google Service account and download the created p12 file. In the Google Play console you have to configure the access for this account. And you have to add a few sections to your project’s gradle files. You can find instructions for it on the gradle-play-publisher website.

Then you can download all your existing descriptions with this command:

./gradlew bootstrapReleasePlayResources

And to just upload a new apk file for a release or a alpha/beta version use this command:

./gradlew clean publishApkRelease

or this if you are using App Bundles

./gradlew clean publishBundle

It also uploads the contents of the “whatsnew” files as changelog to the Google Play store.

Parsing PDF files with Java or Kotlin

Often information is not available in a computer readable format like JSON, XML or CSV. When only a human readable PDF file is available, one can try to use a PDF parser to retrieve the needed information. There is e.g. Apache Tika that can read PDF files and return the contents as tokens. It can … Continue reading “Parsing PDF files with Java or Kotlin”

Often information is not available in a computer readable format like JSON, XML or CSV. When only a human readable PDF file is available, one can try to use a PDF parser to retrieve the needed information. There is e.g. Apache Tika that can read PDF files and return the contents as tokens. It can be quite useful but it doesn’t return tabular information so if you have a table with empty cells you don’t see which cells are empty and it can be difficult to know to which cell the returned data belongs to.

For this purpose another library called Tabula exists. It provides an easy to use local web page that allows to the tables of a PDF file and export them as CSV or JSON files:

Tabula screenshot running on localhost

You can also embed tabula-java into an own program to use it e.g. in batch jobs. E.g. this Kotlin snippet loads a PDF file pdfFile and writes its contents as JSON into tmpfile:

val tmpfile = File.createTempFile("pdfparser", "json")
val args = arrayOf(pdfFile.absolutePath, "-g", "-l", "-f", "JSON", "-o", tmpfile.absolutePath)

val parser = DefaultParser()
val cmd = parser.parse(CommandLineApp.buildOptions(), args)

val stringBuilder = StringBuilder()
CommandLineApp(stringBuilder, cmd).extractTables(cmd)

From there you can parse the JSON to process it further.

Syncing two calendars (e.g. Exchange into Google Calendar) on iOS and Android

Sometimes people are allowed to see their work calendar on their Android phone or iPhone. But they cannot share the calendar directly with their family to show them when they have work events. For this purpose it would be useful to mirror the work calendar (e.g. the Exchange calendar) into a Google calendar in their … Continue reading “Syncing two calendars (e.g. Exchange into Google Calendar) on iOS and Android”

Sometimes people are allowed to see their work calendar on their Android phone or iPhone. But they cannot share the calendar directly with their family to show them when they have work events. For this purpose it would be useful to mirror the work calendar (e.g. the Exchange calendar) into a Google calendar in their Google account so that they can share it with their family. By mirroring only the times of the events but not the contents (title, location, description) confidential data can be removed and only the important data (the time of the events) is shared.

If you have that problem and would like your family to see your work Exchange calendar, then just do the following:

  1. Create a new empty calendar e.g. “Work” in your Google Calendar account.
  2. Sync your Android phone/iPhone with your Exchange account and your Google Calendar account so that you can see calendars from both accounts.
  3. Install SyncCal for Android ( https://play.google.com/store/apps/details?id=com.calengoo.synccal ) or SyncCal for iOS ( https://itunes.apple.com/us/app/synccal/id796482010?mt=8 ) on your phone and use it to copy the Exchange calendar into your new “Work” calendar in your Google account.
  4. Check if you can see your work events in Google Calendar. If that works fine, you can share the calendar with your family to let them see your work events.

Apple AppStore Available on Google Play

Checking remote webspace with Nagios

My webspace provider offers a simple ssh access to upload and download files. One cannot install any software there and has a limited set of commands. I wanted to check the free space on that server because it often runs out of free space and then new uploads fail. The script on the server The … Continue reading “Checking remote webspace with Nagios”

My webspace provider offers a simple ssh access to upload and download files. One cannot install any software there and has a limited set of commands. I wanted to check the free space on that server because it often runs out of free space and then new uploads fail.

The script on the server

The server does not have a “quota” command and “df” is about the whole filesystem, not just about my webspace. So I used “du -ms .” to check how much data is saved in my webspace. I have creates a small shell script “checkfreespace.sh” and saved it on the server:

#!/bin/bash
export USEDSPACE=`du -ms . | sed "s/[^0-9]*//g"`;
if [ "$USEDSPACE" -lt "9000" ] ; then echo "OK - $USEDSPACE MB used" ; exit 0; else echo "CRITICAL - $USEDSPACE MB used"; exit 2; fi

It checks if less than 9000MB are used and returns “OK” with exit code 0. Otherwise it returns “CRITICAL” with exit code 2. These are keywords that are used by Nagios.

SSH configuration

Then it is necessary to make it possible to login using public key authentication (so that Nagios does not need a password).

  1. Use “chsh nagios” to set the shell of nagios to “/bin/bash”.
  2. Use “su – nagios” to switch to the home directory of nagios.
  3. Create a key pair if necessary e.g. using
    ssh-keygen -t rsa -b 4096 -C your@email.com

    in the .ssh directory of the nagios user and change the owner to the nagios user if necessary.

  4. Append the contents of the file .ssh/id_rsa.pub to the file .ssh/authorized_keys on the server.
  5. Use “chsh nagios” to set the shell of nagios back to “/bin/false”.

Nagios configuration

Finally you have to configure Nagios. Add this to the commands.cfg file:

define command{
	command_name	check_my_free_space
	command_line	/usr/lib/nagios/plugins/check_by_ssh -H ssh.yourserver.com -l yourusername -C "bash checkfreespace.sh" -t 30
	}

Afterward you have to use this new command in your services file, e.g. add this:

define service {
        service_description             Free webspace;
        check_command                   check_my_free_space
        use                             generic-service;
        host_name  android.calengoo.com;
        notification_interval           0 ; set > 0 if you want to be renotified
        normal_check_interval           60
}

Google’s new OAuth2 mechanism for native apps

So far the OAuth2 authentication could be performed with embedded browsers in iOS and Android. However Google has decided that they want apps to use the default browser instead now. One reason is that the default browser might already know the user due to cookies and can shorten the authentication process. The other reason might … Continue reading “Google’s new OAuth2 mechanism for native apps”

So far the OAuth2 authentication could be performed with embedded browsers in iOS and Android. However Google has decided that they want apps to use the default browser instead now. One reason is that the default browser might already know the user due to cookies and can shorten the authentication process. The other reason might be that apps could have theoretically captured the entered password when using an embedded browser. Anyway to switch an iOS app from the old authentication method using GTMOAuth2ViewControllerTouch to the new using OIDAuthorizationRequest requires only a few steps due to the useful library GTMAppAuth:

  1. Create a file called “Podfile” and use it to download and install GTMAppAuth:
    target 'YourProjectName' do
     platform :ios, '7.0'
     pod 'GTMAppAuth'
    end
  2. Install Cocoapods if necessary and then run
    pod install
  3. Open the created Xcode workspace file. Delete the following old files if you have them:
    GTMGatherInputStream.h
    GTMGatherInputStream.m
    GTMMIMEDocument.h
    GTMMIMEDocument.m
    GTMReadMonitorInputStream.h
    GTMReadMonitorInputStream.m
  4. Add a property to your AppDelegate.h file:
    @property(nonatomic, retain) id currentAuthorizationFlow;
  5. Add a handler to your AppDelegate.m file in the application:openURL:sourceApplication:annotation: method. Put this right at the start of the method:
    if ([_currentAuthorizationFlow resumeAuthorizationFlowWithURL:url]) {
     _currentAuthorizationFlow = nil;
     return YES;
    }
  6. Now you are ready to replace your old authentication code which used GTMOAuth2ViewControllerTouch with the new code (taken partially from the GTMAppAuth website):
    OIDServiceConfiguration *configuration = [GTMAppAuthFetcherAuthorization configurationForGoogle];
    
    OIDAuthorizationRequest *request = [[[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
     clientId:GOOGLE_CLIENT_ID
     clientSecret:GOOGLE_CLIENT_SECRET
     scopes:@[OIDScopeEmail, @"https://www.googleapis.com/auth/calendar"]
     redirectURL:[NSURL URLWithString:@"com.example.yourapp:/oauthredirect"]
     responseType:OIDResponseTypeCode
     additionalParameters:nil] autorelease];
    
     // performs authentication request
     AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
     appDelegate.currentAuthorizationFlow =
     [OIDAuthState authStateByPresentingAuthorizationRequest:request
     presentingViewController:self
     callback:^(OIDAuthState *_Nullable authState,
     NSError *_Nullable error) {
     if (authState) {
     // Creates the GTMAppAuthFetcherAuthorization from the OIDAuthState.
     GTMAppAuthFetcherAuthorization *authorization = [[[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState] autorelease];
  7. Using the authorization result you can now call your existing handler:
    [self viewControllerFinishedWithAuth:authorization error:error accessToken:authState.lastTokenResponse.accessToken];
     NSLog(@"Got authorization tokens. Access token: %@",
     authState.lastTokenResponse.accessToken);
     } else {
     NSLog(@"Authorization error: %@", [error localizedDescription]);
     }
     }];
    
    }
    
    - (void)viewControllerFinishedWithAuth:(id )auth error:(NSError *)error accessToken:(NSString *)accessToken {
     if (error == nil) {
     // OAuth2 Login was successful
     // Serialize to Keychain
     [GTMOAuth2KeychainCompatibility saveAuthToKeychainForName:keychainNameOAuth2
     authentication:auth];

    Now you can use “accessToken” to access Google services. And due to GTMOAuth2KeychainCompatibility you can keep your existing functions that load the authentication data from the keychain.

  8. In the Info.plist file of your app you have to configure the “com.example.yourapp” URL mentioned above so that the browser can open your app and send you the result:
    CFBundleURLTypes
    
        
            CFBundleTypeRole
            Editor
            CFBundleURLSchemes
            
                com.example.yourapp
            
        
    
    

So that’s all you have to change for an existing iOS app. You can find further information in Google’s blogpost.

Search apps for old iOS versions in the Apple AppStore

Looking for a way to find iOS apps for an older iOS device that does not support the latest iOS version? Here you can search the AppStore and view the release date and the current minimum OS version. Using the release date you can determine if there might be an older version of the app … Continue reading “Search apps for old iOS versions in the Apple AppStore”

Looking for a way to find iOS apps for an older iOS device that does not support the latest iOS version? Here you can search the AppStore and view the release date and the current minimum OS version. Using the release date you can determine if there might be an older version of the app that supports an older iOS version than the current minimum OS version. When installing the app on and old device the AppStore will usually ask you if you would like to install an old version that is compatible to your device.




Version Rating Release date Price Title
{{row.minimumOsVersion}} {{row.averageUserRating}} {{row.releaseDate}} {{row.formattedPrice}} {{row.trackName}}

Using a free SSL certificate from Let’s encrypt with Jetty

Let’s encrypt offers free SSL certificates that can also be used with Jetty. The following steps show how to get an install such a certificate: Installation To install the letsencrypt client on a Linux system, just enter these commands: $ git clone https://github.com/letsencrypt/letsencrypt $ cd letsencrypt $ ./letsencrypt-auto –help Request the certificate To request the … Continue reading “Using a free SSL certificate from Let’s encrypt with Jetty”

Let’s encrypt offers free SSL certificates that can also be used with Jetty. The following steps show how to get an install such a certificate:

  1. Installation
    To install the letsencrypt client on a Linux system, just enter these commands:

    $ git clone https://github.com/letsencrypt/letsencrypt
    $ cd letsencrypt
    $ ./letsencrypt-auto --help
  2. Request the certificate
    To request the certificate run this command:

    ./letsencrypt-auto certonly -d yourdomain.com --webroot -w /var/www/

    To verify the address of your server letsencrypt needs to know the directory of your http server. In this example an Apache is used with the directory /var/www/ (and Jetty runs only on the https port).

  3. Convert the certificate into a format Jetty can use
    openssl pkcs12 -export -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem -inkey /etc/letsencrypt/live/yourdomain.com/privkey.pem -out fullchain_and_key.p12 -name jetty
    keytool -importkeystore -destkeystore keystore_le -srckeystore fullchain_and_key.p12 -alias jetty
    keytool -import -destkeystore keystore_le -file /etc/letsencrypt/live/yourdomain.com/chain.pem -alias root
  4. Install the certificate in Jetty
    Just reference the keystore_le file that you have created in the etc/jetty-ssl.xml file:

    /
    /
    
  5. Stop and restart Jetty

URLEncode Online

Here is a simple form that can URLEncode a given text. This can be useful when programming or writing HTML pages. Text: Convert UrlEncode:

Here is a simple form that can URLEncode a given text. This can be useful when programming or writing HTML pages.

Text:



UrlEncode:

Free Table Element/Plugin for RapidWeaver and Stacks

If you are looking for a simple and free way to add a table to your Stacks page, you can use one of these, just unzip them and copy them into ~/Library/Application Support/RapidWeaver/Stacks before starting RapidWeaver: There are two variants: With custom Stack Elements in each cell: Download FreeTableStack.stack With text in each cell: Download … Continue reading “Free Table Element/Plugin for RapidWeaver and Stacks”

If you are looking for a simple and free way to add a table to your Stacks page, you can use one of these, just unzip them and copy them into ~/Library/Application Support/RapidWeaver/Stacks before starting RapidWeaver:

Screen Shot 2015-12-07 at 12.56.36

There are two variants:

With custom Stack Elements in each cell:

Screen Shot 2015-12-07 at 12.50.29

Download FreeTableStack.stack

With text in each cell:

Screen Shot 2015-12-07 at 12.50.46

Download FreeTableTextStack.stack

Settings:

Both Stacks Element allow you to configure the columns and rows of your table and you can specify the colors for the header cells and the lines:

Screen Shot 2015-12-07 at 12.50.56

If you would like to add an own style, just open the .stacks file and edit the styles.css file.

Building simple RapidWeaver Stack Elements

I am using RapidWeaver for a few websites. The “Stacks” plugin is really useful and makes RapidWeaver very flexible. You can add new “Stack Elements” to your library in RapidWeaver to get new ways to format or style your content. Most “Stack Elements” have to be bought. Some are really good and worth the money … Continue reading “Building simple RapidWeaver Stack Elements”

I am using RapidWeaver for a few websites. The “Stacks” plugin is really useful and makes RapidWeaver very flexible. You can add new “Stack Elements” to your library in RapidWeaver to get new ways to format or style your content. Most “Stack Elements” have to be bought. Some are really good and worth the money but if you only want something really simple you can easily do it yourself for free. Just follow the steps below:

First you can download a simple example project that contains a nearly empty Stack Element that contains only text:

SimpleExample.stack

Just unzip it and copy it into your Stacks directory ~/Library/Application Support/RapidWeaver/Stacks to make it appear in RapidWeaver (after the next restart):

Screen Shot 2015-12-07 at 09.41.48

When you insert it into a page you can enter some text:

Screen Shot 2015-12-07 at 09.43.25

This text will then simply appear on the website. Until this point it certainly isn’t very useful yet. But now you can start customizing it to your needs:

Open ~/Library/Application Support/RapidWeaver/Stacks, right click on “SimpleExample.stack” and choose “Show Package Contents”. You should find three files:

  • Info.plist: Here you can change the version number and add your own ID.
  • styles.css: Here you can enter any CSS styles you need.
  • template.html: This is the HTML file that will be inserted into the page. It can contain HTML code and certain variables that Stacks will replace with content. In this example it contains only a div with the keyword “%text%”, which means that your page contains text that should be inserted here.

Now try to modify the template.html file. Add a second div section like this:

div id="SimpleExample%id%">
%text%
%text%

Then click on “Developer > Reload” in RapidWeaver:

StacksDeveloperButton

Afterward your Stacks Element should have two text fields:

Screen Shot 2015-12-07 at 09.54.47

To embed other Stacks Elements just write “%slice%” instead of “%text%” in your template.html file:

Screen Shot 2015-12-07 at 09.55.45

This way you can easily add your own custom Stack Elements, style them with CSS and use them in your projects.

You can find a reference explaining all Stacks variables and the folder structure on the Stacks API page.