macOS VPN adventures

I use a VPN to connect for work, and have been having some issues with my MacBook Pro. Mostly, on occasion, the internet connectivity would not work.

The way I found to work around this issue was to go into the advanced settings for the VPN and hard code the DNS server of 8.8.8.8 in there. After doing that, it seemed to work much more solidly.

As a bonus tip, if you happen to use VMware Fusion on your Mac to run a Windows VM, I would also recommend going into the network settings for your VM and put the networking to bridge from your Mac instead of going directly to your wi-fi, or otherwise your VM will not communicate through the VPN you have running on your Mac at the same time.

Find the bundle ID of an app in the App Store

Have you ever had to find the bundle ID of an app in the App Store? Well if you have, there does not seem to be a direct way to do it, so here is how I found the information.

First, use the iTunes Link Maker to search for iOS apps, find the app you need to discover the bundle ID for, and click on it. This will pull up a screen with an embed code link, find the numeric ID code.

Then, visit this link, replacing the X’s with the numeric ID you just found:

https://itunes.apple.com/lookup?id=XXXXXXXXX

After you plug in your numeric ID, the Apple site should spit back a JSON file in response, look for the bundleId entry.

BTW, I am a day late, but Happy 40th Anniversary to Slap Shot, one of the finest cinematic masterpieces of all time.

Eliminate noise from the iOS Simulator console

If you find that you are getting a lot more stuff showing up on the console when debugging your app in the Simulator, you are not alone. Luckily, there is a way to eliminate noise from the iOS Simulator console output.

To do this, go into the scheme editor for your target, select the Run Debug option on the left, select the Arguments tab on the right, and under Environment Variables, click the + button to add a new one called OS_ACTIVITY_MODE, and set its value to false.

BTW, a posthumous Happy Birthday to the King, Elvis Presley.

Advent of Code 2016

Well folks, it is the holiday season once again. That only means one thing… Advent of Code 2016 is upon us!

Once again, I have decided to do this undertaking in Swift to help me get familiar with the language and the transition from Swift 2 (that I used in last year’s exercise) to Swift 3.

It seems harder this year than last, as I am struggling to keep up. If you want to check out my lame progress, please visit:

https://github.com/Wave39/AdventOfCode2016

BTW, Happy Holidays everyone!

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.