Posts Tagged iPhone

codesign IPA and the code object is not signed at all problem

You know this journey starts with, “…I was so excited to get Mountain Lion and download the new Xcode.”  I’m now absolutely shocked as for the first time, I’m faced with a strange and unique predicament.  I cannot archive one of my commonly archived for Ad Hoc developer release iOS applications.  What happened?  Where did it start breaking?  I’ll share the facts here and maybe, just maybe, this might help out some poor soul out there.

Let’s start by saying this, how do you even know you’re having this issue?  The first sign of trouble is you build an archive file in Xcode for an “Ad Hoc” release.  The last step finishes up with a code signing or “codesign” process and a final saving of the IPA file.   Everything seems to work properly.   You then do one of the following, install via iTunes or upload the IPA to Test Flight.  All seems fine and grand.  The trouble has just begun.  Your users will begin reporting to you that they cannot download or worse they are seeing the “Failed to install” error.  You’re already in this hole now… what is going on?

My first gut reaction was to start building another archive and then another and each one had the same issue.  I finally realized that the Xcode Organizer tool was going to help me out.  I did the install using iTunes on my iPad 3 and monitored the iPad 3 console in Organizer.

Aug 28 21:07:55 unknown installd[7066] <Error>: unrecognized status -67068 from codesigning library
Aug 28 21:07:55 unknown installd[7066] <Error>: 00403000 verify_signer_identity: Could not copy validate signature: -402620415
Aug 28 21:07:55 unknown installd[7066] <Error>: 00403000 preflight_application_install: Could not verify executable at /var/tmp/install_staging.6ua8Zg/foo_extracted/Payload/MySpecialApp.app
Aug 28 21:07:55 unknown com.apple.itunesstored[7074] <Notice>: MobileInstallationInstall: failed with -1
Aug 28 21:07:55 unknown installd[7066] <Error>: 00403000 install_application: Could not preflight application install
Aug 28 21:07:56 unknown installd[7066] <Error>: 00403000 handle_install: API failed
Aug 28 21:07:56 unknown installd[7066] <Error>: 00403000 send_message: failed to send mach message of 71 bytes: 10000003
Aug 28 21:07:56 unknown installd[7066] <Error>: 00403000 send_error: Could not send error response to client

I can’t tell you how upsetting it was to see this error and to know that Xcode when archiving did not even make a peep about a code signing error.  I quickly opened up my friendly terminal and located my IPA file that I had just attempted to install.  I ran the famous command “codesign” and here is what it looks like.

Chris-Danielsons-MacBook-Pro-2:Desktop myUserAcct$ codesign -dvvv MySpecialApp.app
MySpecialApp.app: code object is not signed at all

So it’s clear to me that Apple has a fairly major issue on their hands that has seemingly let the user wander mindlessly into a trap thinking they were on a great journey of sorts.

So here is the question, how does one correct this issue?  Continuing to fail miserably… here is what I have done thus far to attempt to correct the issue.

  1. I have verified that all my certificates are in order.  Deleted my mobile provisioning profiles manually, re-added them from the Apple developer portal.
  2. Open Disk Utility and do a full verify and repair disk permissions.
  3. Do a full shutdown and startup of my computer.

None of these processes have fixed this issue.

I finally figured out the solution by trial and error.  In my case I had a folder name that matched the “Product Name” variable under build settings.   This also matched the entire project name!  So I simply changed one field.  I changed the “Build Settings” -> “Product Name” .  The value of MySpecialApp was changed to My-SpecialApp.  That was simply it!  I then logged back into the Apple developer portal and created a new App ID and mobile provisioning profiles for development and distribution and the rest is history.  My releases now work when deployed via the Ad Hoc distribution.

A final note on this.  This is definitely a bug that Apple should either alert the user that they have done something wrong and enable some sort of automated corrective action.  After archiving I still receive:

codesign -dvvv My-SpecialApp.ipa
My-SpecialApp.ipa: code object is not signed at all

So what gives? Something is very wrong here, but this solution works for now.

 

, , , , , , , ,

2 Comments

Unity3D File Based Assetbundles on the iPhone

Let me start off by saying that Unity3D is a really great game engine. Let me also say that I wish the documentation was as great as the engine is. Sadly, it’s difficult to figure out some of the more powerful features of Unity3D without significant trial and error.

Please note, that I have read that the usage of Assetbundles on the iPhone can be memory intensive and may or may not fit your needs per your project. I am just putting this information here so that others can see how to do this. Pro Tip: What this means to you? Profile the heck out of your code, pre-assetbundles and after integrating assetbundles.

Assumptions:
1. You know or are familiar Unity3D 3.3.
2. You can code in C#.
3. You’re an ace at creating prefabs in Unity.
4. You’re using Unity3D 3.3 Pro and iOS Pro.

OK, if you’re still feeling good, let’s bounce into this how-to.

Create the Project

Open up a new project in Unity3D and set it up for “iPhone” iOS. Feel free to name it whatever passes your way.

In the project hierarchy, let’s go ahead and create a simple directory structure as follows:

/Example Project/
/Example Project/iphone/
/Example Project/iphone/objects/
/Example Project/iphone/materials/

Hit save after doing this and save your default scene and name it whatever you want.  In my case, I named it “test”.

Though, this is a near complete looking example (image to the right), the basic structure should look like the image to the right here.

Add at least one prefab to your project. I have added two prefabs here, “box” and “ABCD”. Both are just tests and contain a cube prefab with a simple texture applied. Make sure that the materials referenced by your prefabs have the following attributes. 1. They are named the same as the prefab. (See the image above!). 2. They are stored in the materials folder underneath the iphone folder.

UnityEditor Coding Time

When working on assetbundles, the first thing you have to do is generate them. Unfortunately, Unity3D does not have anything built in for generating these files except for a UnityEditor API. The UnityEditor script can only be run from inside the Unity3D editor tool. It typically appears as a menu item after the script has been successfully compiled. So if you can code, then you’re in good shape.

Let’s create the UnityEditor script. Create a new C-Sharp script in a /Plugins/ folder (create it if it doesn’t already exist) at the root of your project and name it MPCreateAssetBundle. Copy and paste the following into it. Please note: some of this code was borrowed from Unity’s own Character Customization tutorial on their website.

View Code CSHARP
using System;
using System.IO;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Object=UnityEngine.Object;
 
public class MPCreateAssetBundle : MonoBehaviour {
 
	private static String[] mpAssetDir = new String[]{"iphone", "ipad", "macosx", "pc"};// , "universal"}; <-- not needed, use the /Resources/ folder.
 
	[MenuItem("Custom/Monkey Prism/Create All Assetbundles #&i")]
	public static void Execute() {
		Debug.Log("Creating Assetbundles");
		bool blnFound = false;
		String currentDir = null;
		foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets)) {
			blnFound = true;
 
			if (o.name.Contains("@")) continue; //animations!
			String assetPath = AssetDatabase.GetAssetPath(o);
			if (!File.Exists(assetPath)) {
				currentDir = assetPath;
				continue; //Files only.
			}
			//Only check those directories that we have specified in the mpAssetDir
			Debug.Log(assetPath);
 
			String currentBuildType = null;
			foreach (String s in mpAssetDir) {
				if (assetPath.Contains("/"+s+"/")) {
					currentBuildType = s;
					break;
				}
			}
			if (currentBuildType == null) continue; //if the directory is not found to be one from the mpAssetDir bail out.
 
			string assetBundleName = null, genericName = null;
 
			List<Object> toinclude = new List<Object>();
 
			//Generate pre-fabs for everything in the finished pre-fab directory.
 
			if (o.GetType() == typeof(GameObject)) {
				Debug.Log("GameObject " + currentDir);
 
				String d = CharacterRoot((GameObject)o);
				d += "materials/";
				Debug.Log(d);
				List<Material> materials = CollectAll<Material>(d);
				Debug.Log("materials count=" + materials.Count);
 
				genericName = o.name.ToLower();
				assetBundleName = currentBuildType + "-prefab-" + genericName;
				//Package up the prefabs in the iPhone directory.
				toinclude.Add(o);
				//Do we need to add in a material?  I think so.
				foreach (Material m in materials) {
					Debug.Log("Material Name=" + m.name);
                    if (m.name.Contains(genericName)) {
						toinclude.Add(m);
						Debug.Log("Added a new material!");
					}
				} //end foreach
 
			} 
 
			if (assetBundleName == null) continue;
 
 
			// Create a directory to store the generated assetbundles.
            if (!Directory.Exists(AssetbundlePath))
                Directory.CreateDirectory(AssetbundlePath);
 
            // Delete existing assetbundles for current object
            string[] existingAssetbundles = Directory.GetFiles(AssetbundlePath);
            foreach (string bundle in existingAssetbundles) {
                if (bundle.EndsWith(".assetbundle") && bundle.Contains("/assetbundles/" + assetBundleName))
                    File.Delete(bundle);
            }
 
			//Directories expected.
			Debug.Log("currentBuildType = " + currentBuildType);
 
			//path = AssetbundlePath + bundleName + ".assetbundle";
			if (toinclude.Count > 0) {
				String path = AssetbundlePath + assetBundleName + ".assetbundle";
				Debug.Log(path);
				if (currentBuildType.Equals(mpAssetDir[0]) || currentBuildType.Equals(mpAssetDir[1])) //iPhone & iPad
					BuildPipeline.BuildAssetBundle(null, toinclude.ToArray(), path, BuildAssetBundleOptions.CollectDependencies, BuildTarget.iPhone);
				else //TODO: might need to condition further and might want to use an enum with the conditional.
					BuildPipeline.BuildAssetBundle(null, toinclude.ToArray(), path, BuildAssetBundleOptions.CollectDependencies);
			}
 
 
		} //end foreach
 
		if (!blnFound) {
			Debug.Log("no objects were found for building assets with.");	
		}
	}
 
	public static string AssetbundlePath
    {
        get { return "assetbundles" + Path.DirectorySeparatorChar; }
    }
 
	// This method loads all files at a certain path and
    // returns a list of specific assets.
    public static List<T> CollectAll<T>(string path) where T : Object
    {
        List<T> l = new List<T>();
        string[] files = Directory.GetFiles(path);
 
        foreach (string file in files)
        {
            if (file.Contains(".meta")) continue;
            T asset = (T) AssetDatabase.LoadAssetAtPath(file, typeof(T));
            if (asset == null) throw new Exception("Asset is not " + typeof(T) + ": " + file);
            l.Add(asset);
        }
        return l;
    }	
	// Returns the path to the directory that holds the specified FBX.
    static string CharacterRoot(GameObject character)
    {
        string root = AssetDatabase.GetAssetPath(character);
        return root.Substring(0, root.LastIndexOf('/') + 1);
    }
 
}

Once this is completed, you’ll want to do two things.
1. Select (by moving your mouse over and left-clicking on it once) the iphone folder under “Example Project”.
2. Run the script as shown in the image:

So let’s back up for a second and look at what we just did. We created a project, created some folders within the project, placed prefabs into the iphone folder and created a UnityEditor script. Upon running this script, a new directory named “assetbundles” would be created.

This directory is not going to be visible to you until you open finder (on Mac) or explorer (on Windows) as it is located on the file system. (see the image above). Inside this folder you should see your prefab(s) named now as: iphone-prefab-<my prefab name>.assetbundle. If you are seeing this, congratulations, you’ve now created your own assetbundles uniquely per prefab.

Generic GameObject and a Simple Script

If you’ve come this far, great work! We’re nearly done.
Let’s create a new GameObject under the Hierarchy.

Now we’re going to write a simple script to instantiate the assetbundles we assembled earlier. Create a new C-Sharp script in the /Plugins/ folder and name it “Example”. Copy and paste the following code into it:

View Code CSHARP
using System;
using UnityEngine;
using System.Collections;
 
public class Example : MonoBehaviour {
	private WWW www;
	private AssetBundleRequest gameObjectRequest;	
	// Use this for initialization
	IEnumerator Start () {
        //TODO: change the name of the file below!!!
		String strPath = "file://" + Application.dataPath + "/../assetbundles/iphone-prefab-box.assetbundle";
		Debug.Log(strPath);
		www = new WWW(strPath);
		yield return www;
        /* TODO: change the name "Box" to match the name of your prefab that you compiled into the assetbundle on step 1. */
		AssetBundleRequest request = www.assetBundle.LoadAsync("Box", typeof(GameObject));
		yield return request;
		Instantiate(request.asset, new Vector3(3f, 0f, 0f), Quaternion.identity);
		Instantiate(request.asset, new Vector3(0f, 0f, 0f), Quaternion.identity);
		Instantiate(request.asset, new Vector3(-3f, 0f, 0f), Quaternion.identity);
		www.assetBundle.Unload(true);
	}
        void Update() { }
}

NOTE: Make sure to change the TODO line in the code to match your file name! If you don’t do this, it might not work!

We’re nearly done! Drag your Example.cs script onto the GameObject you created earlier. Here is how my project looks:

Build Time

We’re now going to build this codebase so that you can run it on your iOS device for testing. I’m going to skip the painful steps of creating a code signing certificate and all that jazz. We’re instead going to focus on how to get the actual assetbundle onto your iOS device in an area that will be accessible to the “Application.dataPath” call in your code!

1. Build the Unity project for iOS.
2. XCode should automatically open.
3. Within XCode you are going to need to tell it about your assetbundles folder! Open up finder or explorer and locate the assetbundles folder that was generated by the UnityEditor script we discussed earlier.
4. Drag and drop the assetbundles folder into XCode at the root of the iOS project. (You should see a prompt as follows)

5. Click “Finish”.

This will then look something like this:

6. Build the code using XCode and run it on your iOS device.

If everything works properly, you should see one of the prefabs instantiate on your iOS screen. That is all there is to it! I think you’ll find that this isn’t as bad as one might imagine, but it does require some serious fishing around in code examples and heavily crawling the Unity forums. The only way I figured this out was by trial and error, heavy amounts of Debug.Log calls and 3 pots of coffee. I’m now going to go and grind my teeth on my level editor.

Edit: I have one of my original forum posts here as well regarding this issue. Unity3D Forum

, , , , , , ,

19 Comments

iPhone users able to build a shinier world, one turd at a time

This blog usually focuses on software development, but I can’t resist sharing this with all of you out there.  Have a good laugh!

MaxPowerSoft Puts a New Polish on an Old Adage: You Actually Can Polish a Turd

Polish It now available at the iPhone App Store

SAN DIEGO, CA (May 24, 2010) – MaxPowerSoft (www.maxpowersoft.com) today announced the release of Polish It, an iPhone application designed to facilitate “a shinier world, one turd at a time”. Available for $0.99 at Apple’s iPhone App Store, ‘Polish It’ is both a literal and cute/comedic take on the old and well-known phrase “You can’t polish a turd”. Your goal is simple: Choose a turd you like, and polish it! Utilize the touchscreen and your finger for polishing, tilt the phone to maneuver, and snap a photo at anytime to share.

“We wanted to reach out and give frustrated workers, students, and really all curious people in general, the powerful ability to truly polish a turd,” says Nic Danielson, Director of Marketing. “MaxPowerSoft has created an innovative new technology that allows one to therapeutically accomplish the task of polishing turds in the palm of your hand, no matter where you are, and on a whim to boot – most importantly, it can be done without the need for any sanitization processes.  There really is nothing else like it in the market, or the world for that matter.”

Features of Polish It include:

  • Objects rendered in full 3D.
  • Choose from over 10 objects to polish.
  • Simple controls: Touch to polish, Tilt phone to maneuver.
  • Snap a photo and send to your friends.
  • More features to come.

Pricing and Availability:

Polish It is available for $0.99 at the iPhone App Store:

http://itunes.apple.com/us/app/polish-it/id345199287?mt=8

, , , , , , ,

1 Comment

Could not send unregistration request to daemon

During a debug process have you seen any of the following lines in your debugger/console logs?

void CLClientInvalidate(__CLClient*)",could not send unregistration request to daemon

or…

CLClientRegister: could not send registration request to daemon

If so, you’ve probably already seen this Apple support link:  http://discussions.apple.com/message.jspa?messageID=8408930

Well, I’m just going to validate a few things here for you.  (Before continuing this… check your code after briefly reading this blog.

  1. You will have to restore your iPhone.  (This is the solution that worked for me).  Please post a comment if you find a better solution.
  2. If you are coding using CLLocationManager you will more than likely notice that you only get 1 set of GPS values before the message starts appearing.  Also, the CLLocationManager startUpdatingLocation method will only call your delegate once.  (That is what was happening on my iPhone).
  3. If you dig through your iPhones “crash logs” via the Organizer application, you’ll more than likely witness that many applications are crashing.

I tried a multitude of workarounds and the only thing that sadly worked was a “restore” which took over 1 hour to complete.  I will say this, my iPhone runs a lot faster now!

, , , , ,

8 Comments

Apple iPhone Web Kit with Activity Indicator

Welcome to the club of searching for an overly simple UIWebView a.k.a. WebKit example! In this example, I’ll show you simply how to hand code a quick UIWebView into your program as well as to add a UIActivityIndicatorView a.k.a. an activity indicator. Without jabbing Apple too hard here, the documentation is pretty bad and that is why it’s nice to have an example just shown to you as-is. I hope this example helps shine a light on the situation for anyone wanting to implement a nice and quick Apple iPhone WebKit solution.

 
#import <UIKit/UIKit.h>
 
@interface FirstViewController : UIViewController <UIWebViewDelegate>
{
	UIWebView *myWebView;
	UIActivityIndicatorView *activityIndicator;	
}
/*
Inside the @implementation FirstViewController ... 
*/
- (void)viewDidLoad { //We have a NIB file in play here, so I dropped the loadView here.  Just make sure that your loadView is not getting called twice!
    [super viewDidLoad];
    [self loadView];
}
 
- (void)loadView {
	UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
	self.view = contentView;	
 
	CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
	webFrame.origin.y = 0.0f;
	myWebView = [[UIWebView alloc] initWithFrame:webFrame];
	myWebView.backgroundColor = [UIColor blueColor];
	myWebView.scalesPageToFit = YES;
	myWebView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
	myWebView.delegate = self;
	[self.view addSubview: myWebView];
	[myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.maxpowersoft.com/"]]];
 
	activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
	activityIndicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
	activityIndicator.center = self.view.center;
	[self.view addSubview: activityIndicator];
}
 
- (void)dealloc {
	[activityIndicator release];
	[myWebView release];
        [super dealloc];
}
 
#pragma mark WEBVIEW Methods
 
- (void)webViewDidStartLoad:(UIWebView *)webView
{
	// starting the load, show the activity indicator in the status bar
	[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
	[activityIndicator startAnimating];
}
 
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
	// finished loading, hide the activity indicator in the status bar
	[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
	[activityIndicator stopAnimating];
}
 
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
	// load error, hide the activity indicator in the status bar
	[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
 
	// report the error inside the webview
	NSString* errorString = [NSString stringWithFormat:
							 @"<html><center><br /><br /><font size=+5 color='red'>Error<br /><br />Your request %@</font></center></html>",
							 error.localizedDescription];
	[myWebView loadHTMLString:errorString baseURL:nil];
}

That is all there is to it. It’s really simple as you can see. Feel free to copy and paste accordingly.

, , , , ,

14 Comments