Log all SQL statements in an Android app

If you are using SQLite as your data store in an Android app, and you want to try and trace through the SQL statements that are occurring, it can be painful, especially if you are working with a large code base that you may not be 100% familiar with.

Luckily, there is a super easy way to do this with no code changes. Once you have opened the simulator, go to the terminal and execute these commands:

adb shell setprop log.tag.SQLiteLog V
adb shell setprop log.tag.SQLiteStatements V
adb shell stop
adb shell start

Then, in the Android monitor, you will probably want to filter by SQLiteStatements to see the relevant entries.

Ignore warnings in a specific file in Xcode

If you use any 3rd party or open source code in your iOS or macOS application, you know how deflating it is to get your code all compiling with no errors or warnings, only to have your open source code spit out lots of warnings. If only there were a way to ignore warnings in a specific file in Xcode…

Well as it turns out, you can go into the Build Phases section in your target’s settings, find the file or files you want to disable warnings for, double click on the Compiler Flags, and add in the following entry:

-w -Xanalyzer -analyzer-disable-all-checks

This entry will have the additional benefit of also disabling the Clang static code analysis warning messages for the files, which can be just as annoying as the warnings.

BTW, Happy 60th Birthday to the Wizard, Jordan Rudess of Dream Theater. Jennifer and I saw them here in Columbus tonight as they performed The Astonishing Live, and the show was great.

METHOD_LOG

I have a lot more projects that I am working on at my new gig, and as such, I am always looking for my METHOD_LOG definition. It is a quick define that I put in my Objective-C code so that I can log what class and method I am in, without having to type out a description of the class and method into an NSLog statement.

So here is the code for METHOD_LOG, along with a DebugLog define that I use quite often instead of NSLog:

#if defined(DEBUG)
    #define METHOD_LOG (NSLog(@"METHOD_LOG: %@ %s", NSStringFromSelector(_cmd), __FILE__))
    #define DebugLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
    #define METHOD_LOG
    #define DebugLog(...)
#endif

BTW, Happy International Caps Lock Day.

View the Android activity stack

Have you ever been developing an Android app, and wanted to find out what activity you were looking at on the screen without spelunking through mountains of source code? Well luckily, there is a quick way to view the Android activity stack.

(Please note that these instructions are for use on a Mac. The corresponding Windows way of doing things is undoubtedly similar.)

If you have ADB installed and running on the command line, then go into Terminal and enter the following command:

adb shell dumpsys activity | grep -i run

Upon doing this, you should see a listing that looks something like this:

mbp:~ user$ adb shell dumpsys activity | grep -i run
    Running activities (most recent first):
        Run #5: ActivityRecord{3d31e5ec u0 com.yourcompany.yourapp/.ui.CustomerDetailActivity t211}
        Run #4: ActivityRecord{18b02af2 u0 com.yourcompany.yourapp/.ui.CustomerListActivity t211}
        Run #3: ActivityRecord{517ab43 u0 com.android.settings/.Settings t180}
        Run #2: ActivityRecord{2e389c3c u0 com.android.chrome/com.google.android.apps.chrome.document.DocumentActivity t179}
        Run #1: ActivityRecord{8583e3d u0 com.google.android.googlequicksearchbox/com.google.android.sidekick.main.optin.NewOptInActivity t153}
        Run #0: ActivityRecord{14e94b15 u0 com.google.android.googlequicksearchbox/com.google.android.apps.gsa.legacyui.VelvetActivity t153}
(more stuff after, not important)

If you look at the top of that list, you will see that the CustomerDetailActivity class is at the top of the activity stack.

Keep in mind that you may need to get ADB set up on your Mac, the easiest way is to install the tools through brew, and here are the Terminal commands necessary to do this:

1. Install homebrew:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2. Install ADB:

brew install android-platform-tools

3. Test ADB:

adb devices

That last command above will just verify that you have a device hooked into your computer. This also appears to work with the Android emulator provided by Android Studio, but if you are using Genymotion, it should work fine with that one as well.

BTW, Happy 50th Birthday to Star Trek, which debuted on American television on this date way back in 1966.

P.S. Credit where credit is due: View activity stack in Android – Stack Overflow and Installing ADB on MAC OS X – Stack Overflow were obviously key.

Codesign error: “Warning: –resource-rules has been deprecated in Mac OS X >= 10.10”

So you are humming along and everything is going great. Then all of a sudden you start getting the error message “Warning: –resource-rules has been deprecated in Mac OS X >= 10.10”, especially if you are using some kind of tool to re-sign code.

Apparently, in your build settings for your target in Xcode, there is a Code Signing Resource Rules Path entry that is no longer supported. Once this is removed and the app is rebuilt, the message should no longer appear. Of course, if you are re-signing an app that you do not have the source code for, this could be a challenge.

Here is the technical note from Apple that describes the issue:

TN2206

BTW, Happy 60th Birthday to the best rock guitar player of all time, Joe Satriani. I am looking forward to seeing Joe in a few weeks at the G4 Experience on Long Island.

Calling a .NET web service endpoint with NSURLSessionUploadTask

I have been going through the process of removing open source components from my apps when Cocoa Touch and the associated frameworks catch up with what I need to do.

Let’s say for the sake of argument you have a .NET web service that looks like this:

using System;
using System.Web.Script.Services;
using System.Web.Services;
 
namespace My_WebRole
{
    /// <summary>
    /// Summary description for CreateCustomer
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [ScriptService]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    // [System.Web.Script.Services.ScriptService]
    public class CreateCustomer : WebService
    {
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public string Create()
        {
            try
            {
                var myName = Context.Request.Form["MyName"];
                var companyName = Context.Request.Form["CompanyName"];
                var db = new MyServicesDataContext();
                var row = new CustomerInformation { MyName = myName, CompanyName = companyName, CreationDate = DateTime.Now };
                db.CustomerInformations.InsertOnSubmit(row);
                db.SubmitChanges();
            }
            catch (Exception ex)
            {
                return ex.ToString();
            }
            return "OK";
        }
    }
}

The NSURLSessionUploadTask class was added in iOS 7, which is sufficiently long enough ago to be stable to implement. (As long as your app is going to require iOS 7 or newer, of course.)

Here is what the code looks like that calls the above web service:

+ (BOOL)pushTheData:(NSString *)myName companyName:(NSString *)companyName
{
    NSMutableString *urlString = [NSMutableString stringWithString:PUSH_DATA_URL];
    NSString *boundary = [NSString boundaryString];
    NSMutableData *body = [NSMutableData data];
 
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", @"MyName"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@\r\n", myName] dataUsingEncoding:NSUTF8StringEncoding]];
 
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", @"CompanyName"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@\r\n", companyName] dataUsingEncoding:NSUTF8StringEncoding]];
 
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
 
    NSURL *url = [NSURL URLWithString:urlString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"POST"];
    [request addValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"];
 
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    configuration.HTTPAdditionalHeaders = @ { @"Content-Type"  : [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] };
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
 
    NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error)
        {
            // handle the error
            return;
        }
 
        NSLog(@"Response: %@", [data utf8String]);
        // do something here
    }];
 
    [task resume];
 
    return YES;
}

The above method uses a category that I have set up off of NSString that creates a new boundary string each time it is called. Here is that method:

+ (NSString *)boundaryString
{
    NSString *uuidStr = [[NSUUID UUID] UUIDString];
    return [NSString stringWithFormat:@"Boundary-%@", uuidStr];
}

BTW, Happy Birthday to Jeff Beck. He has a new album coming out soon, and I can’t wait to hear it.

Xcode project line counts

If you are looking to find out how many lines of code are in each of the files of your Xcode project, you can use the following command in Terminal after you change into the root folder of your project:

find . \( -iname \*.m -o -iname \*.mm -o -iname \*.h \) -exec wc -l '{}' \+

SpriteKit game background music stopped working

In my SpriteKit game, all of a sudden the background music stopped playing, all I heard was silence no matter what the volume levels were in either the app settings or via the hardware buttons.

I am not sure why this happened, but I was able to figure out how to get it working again. The key was adding an AVAudioSession call before the existing AVAudioPlayer code. Here is some sample code of what I did:

AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
 
NSURL *url = [NSURL fileURLWithPath:@"your_sound_file.caf"];
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[_player setDelegate:self];
[_player prepareToPlay];
[_player play];

BTW, Happy Birthday to Brutus Beefcake. (I couldn’t really find any other good birthdays, deaths, or events in the Wikipedia page for today.)

Xcode test coverage falsely indicates methods covered by testing

If you have a normal Xcode project that you added unit testing to, you may find that the testing code coverage inside of Xcode shows that there is a lot more code being tested than actually is. Or if you have an app that does complex and/or lengthy things in its initialization, you may get tired of waiting for all that stuff to run just because you want to run the tests to see if they pass.

Luckily, I figured out a way to short circuit the app from its normal initialization if you are invoking it for the purposes of testing. Here is the code you would need to put in your app delegate’s didFinishLaunchingWithOptions method, preferably right at the top:

#if defined(DEBUG_VERSION)
    if ([[[NSProcessInfo processInfo] arguments] containsObject:@"-FNTesting"])
    {
        DebugLog(@"The -FNTesting argument is in use, so the app will just create a blank view controller");
        UIViewController *vc = [[UIViewController alloc] init];
        navigationController = [[MyNavigationController alloc] initWithRootViewController:vc];
        [window setRootViewController:navigationController];
        return YES;
    }
#endif

(The #if above uses a compiler variable that is only used in the debug scheme of the application. It’s a good plan all around to do this in your own code.)

Basically, this code only is going to run if your are doing a unit test run, and it just creates a blank view controller and returns.

BTW, Happy Pi Day. I meant to do this posting at 1:59 today to continue the pi theme, but got busy with work and forgot.

Reinforced concrete would be a pretty cool security feature

I was going to upgrade to Windows 10, but I don’t think I can trust any operating system that does not have reinforced concrete…

reinforced_concrete

BTW, a posthumous Happy Birthday to Steve Jobs.