dueling banjos: inter-app communication
TRANSCRIPT
![Page 1: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/1.jpg)
Dueling Banjos(Inter-App Communication)
Michael DorinDan Ratcliff
1Wednesday, March 20, 13
![Page 2: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/2.jpg)
Agenda• Introduction
• That was my Intent!
o Android Inter-App Communication
o Bound and Determined
• UR’all that… and more!
o iOS Inter-App Communication
• Android Security
• IoS Security
2Wednesday, March 20, 13
![Page 3: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/3.jpg)
Introduction
• Inter-application communication promotes development of feature rich applications
• Developers leverage existing services to create rich, ‘seamless’ applications
3Wednesday, March 20, 13
![Page 4: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/4.jpg)
Introduction
• Android and iOS provide messaging systems for communications within and between applications
• These message systems also facilitate attacks
4Wednesday, March 20, 13
![Page 5: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/5.jpg)
• Applications are...Built upon components
• Components
o Activity
o Service
o Broadcast Receiver
o Content Provider
• Inter-app communications
Android Vocabulary
5Wednesday, March 20, 13
![Page 6: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/6.jpg)
• Application startup
• Android creates a 'Linux' process with a single thread of execution
• You can (and probably will) create more than a single thread of execution
• By default, all components of the same application run in the same process
Processes and Threads
6Wednesday, March 20, 13
![Page 7: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/7.jpg)
Component Data Paths
System
Service
ActivityActivity
Service
7Wednesday, March 20, 13
![Page 8: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/8.jpg)
That was my intent
• Intents launch activities and services
• Intents can hold data
“Intents are system messages, running around the inside of the device, notifying applications of various events, from hardware state changes (e.g.,an SD card was inserted), to incoming data (e.g., an SMS message arrived),to application events (e.g., your activity was launched from the device’s main menu).”http://android.programmerguru.com/android-intent-example/
8Wednesday, March 20, 13
![Page 9: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/9.jpg)
Thats ‘intents’
• You may transmit Data in Intents
• You may return Data in Intents
• Implicit intents can launch a variety of activities or services
• Explicit intents explicitly launch one particular activity or service
9Wednesday, March 20, 13
![Page 10: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/10.jpg)
Intent()Create an empty intent.
Intent(String action)Create an intent with a given action.
Intent(String action, Uri uri)Create an intent with a given action and for a given data url.
Intent(Context packageContext, Class<?> cls)Create an intent for a specific component.
Creates an ‘implicit’ intent
Creates an ‘explicit’ intent
Intent Constructors
10Wednesday, March 20, 13
![Page 11: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/11.jpg)
Implicit Intent
The primary pieces of information in an intent are:
• action -- The general action to be performed, such as ACTION_VIEW, ACTION_EDIT, ACTION_MAIN, etc.
• data -- The data to operate on, such as a person record in the contacts database, expressed as a Uri.
Intent(String action, Uri uri)
11Wednesday, March 20, 13
![Page 12: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/12.jpg)
• ACTION_VIEW content://contacts/people/1 -- Display information about the person whose identifier is "1".• ACTION_DIAL content://contacts/people/1 -- Display the phone dialer with the person filled in.• ACTION_VIEW tel:123 -- Display the phone dialer with the given number filled in. Note how the VIEW action does what
what is considered the most reasonable thing for a particular URI.• ACTION_DIAL tel:123 -- Display the phone dialer with the given number filled in.• ACTION_EDIT content://contacts/people/1 -- Edit information about the person whose identifier is "1".• ACTION_VIEW content://contacts/people/ -- Display a list of people, which the user can browse through. This example is
a typical top-level entry into the Contacts application, showing you the list of people. Selecting a particular person to view would result in a new intent {ACTION_VIEW content://contacts/N } being used to start an activity to display that person.
Examples:
http://developer.android.com/reference/android/content/Intent.html
12Wednesday, March 20, 13
![Page 13: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/13.jpg)
Explicit IntentIntent(Context packageContext, Class<?> cls)
The primary pieces of information in an intent are:
Context -- package context where the class you wish to invoke resides
Class -- name of the class
13Wednesday, March 20, 13
![Page 14: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/14.jpg)
• category -- Gives additional information about the action to execute. • type -- Specifies an explicit type (a MIME type) of the intent data. • component -- Specifies an explicit name of a component class to use for the intent. • extras -- This is a Bundle of any additional information
Additional attributes
14Wednesday, March 20, 13
![Page 15: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/15.jpg)
intent = new Intent(this, com.chaski.mobilemarchexample.EasyActivity.class);
startActivity(intent);
Example:Explicit Intent
Activity LaunchedIntra-App
Context
Class Implementing Activity
EasyActivity.java
15Wednesday, March 20, 13
![Page 16: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/16.jpg)
Example:Explicit IntentService LaunchedIntra-App
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.easy_layout); Intent intent = new Intent(this, com.chaski.mobilemarchexample.EasyService.class); intent.putExtra("messenger", messenger); startService(intent);} messenger
Activity launched, now launch a service!
See EasyActivity.java
16Wednesday, March 20, 13
![Page 17: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/17.jpg)
@Override public int onStartCommand(Intent intent, int flags, int startId) { Messenger messenger = intent.getParcelableExtra("messenger"); MyRunnable mr = new MyRunnable(messenger); Thread t = new Thread(mr); t.start(); return Service.START_STICKY; }
Inside the Service(EasyService.java)
....Message message = Message.obtain(null, 1, 0, 0);try { Bundle data = new Bundle(); data.putString("mystring", "myvalue:"+i); message.setData(data); messenger.send(message); } catch (RemoteException e) { }...
within myRunnable
grab messenger
17Wednesday, March 20, 13
![Page 18: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/18.jpg)
packagpublic class EasyActivity extends Activity { MyHandler handler = new MyHandler(); Messenger messenger = new Messenger(handler);
.......
class MyHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: String mydata = msg.getData().getString("mystring"); Toast.makeText(getApplicationContext(), "Got Message:"+mydata, Toast.LENGTH_SHORT).show(); break; case 2: Toast.makeText(getApplicationContext(), "EasyService has ended", Toast.LENGTH_SHORT).show(); default: super.handleMessage(msg); } } }}
Activity Handler
See EasyActivity.java
18Wednesday, March 20, 13
![Page 19: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/19.jpg)
So far
• 2 Examples
• Launch activity with explicit intent and no expectation of returned data
• Launch service with explicit intent with expectation of data passed via messenger/handler
19Wednesday, March 20, 13
![Page 20: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/20.jpg)
Next example
• startActivityForResult - Expect a result from the calling activity
• new activity registers for broadcast receiver
• new activity starts a service
• service finishes, sends message via broadcast
• Activity finishes and returns result
20Wednesday, March 20, 13
![Page 21: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/21.jpg)
Example 3:Explicit Intent
Activity LaunchedIntra-App
intent = new Intent(this, com.chaski.mobilemarchexample.TrivialActivity.class); startActivityForResult(intent,72);
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { String retData = data.getStringExtra("result"); String giantToastString = "onActivityResult-requestCode:"+requestCode+ " "
+"onActivityResult-resultCode:"+resultCode+" "+"returnedData:"+retData; Toast.makeText(this, giantToastString,Toast.LENGTH_SHORT).show(); ... }
requestCode
MainActivity.java
21Wednesday, March 20, 13
![Page 22: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/22.jpg)
*You can do the same thing with a service*It takes a couple Extra Steps though*See simpleActivity.java/simpleService.java
22Wednesday, March 20, 13
![Page 23: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/23.jpg)
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.trivial_layout); receiver = new ResponseReceiver(); registerReceiver(receiver, new
IntentFilter("com.chaski.mobilemarchexample.TrivialActivity.broadcast.update")); Intent intent = new Intent(this,com.chaski.mobilemarchexample.TrivialService.class); this.startService(intent);}
TrivialActivity.java
class ResponseReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(getApplicationContext(), "TrivialService has ended",
Toast.LENGTH_SHORT).show(); } }
TrivialService will communication through a BroadcastReceiver
Or use a BroadcastReceiver
23Wednesday, March 20, 13
![Page 24: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/24.jpg)
@Override public int onStartCommand(Intent intent, int flags, int startId) { MyRunnable mr = new MyRunnable(); Thread t = new Thread(mr); t.start(); return Service.START_STICKY; }
...
public void SendBroadcast(Boolean result, String Msg) { Intent i = new Intent(); i.setAction("com.chaski.mobilemarchexample.TrivialActivity.broadcast.update"); i.putExtra("result", result); i.putExtra("message", Msg); this.sendBroadcast(i); }
TrivialService.java
Response via Broadcast
24Wednesday, March 20, 13
![Page 25: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/25.jpg)
Bound and Determined
• The server in a client-server interface.
• Allows components to send requests and receive responses
• Typically does not run in the background indefinitely
Bound Service
25Wednesday, March 20, 13
![Page 26: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/26.jpg)
Bound Services
• A bound service allows other applications to bind to..to interact with it.
• You must implement the onBind()callback
• This method returns an IBinder object that defines the programming interface that clients can use to interact with the service.
26Wednesday, March 20, 13
![Page 27: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/27.jpg)
Bound Services
• We can use messages as before
• We can invoke functions directly
27Wednesday, March 20, 13
![Page 28: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/28.jpg)
Step 1- Make Servicefinal Messenger myMessenger = new Messenger(new MessageHandler());@Overridepublic IBinder onBind(Intent intent) { return myMessenger.getBinder();}
public class LocalBoundServiceBinder extends Binder { LocalBoundService getService() { return LocalBoundService.this; } }
@Override public IBinder onBind(Intent intent) { return binder; }
You need a binder!
Communicating via a messenger
Communicating via local methods
See BoundMessageService.java
See LocalBoundService.java
28Wednesday, March 20, 13
![Page 29: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/29.jpg)
class BoundMessageServiceConnection implements ServiceConnection { public void onServiceDisconnected(ComponentName name) { Log.i(TAG, "Service Disconnected"); }
public void onServiceConnected(ComponentName name, IBinder service) { messageBinder = (IBinder) service; myMessenger = new Messenger(service); } };
BoundActivity.java
localBoundServiceConnection = new LocalBoundServiceConnection();intent = new Intent(this, com.chaski.mobilemarchexample.LocalBoundService.class);boundServiceBound = bindService(intent, localBoundServiceConnection, Context.BIND_AUTO_CREATE);
Make a connection, Start the service!
29Wednesday, March 20, 13
![Page 30: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/30.jpg)
Use the service
localBoundService.getRandomNumber();BoundActivity.java
/** method for clients */ public int getRandomNumber() { return mGenerator.nextInt(100); }
BoundService.java
30Wednesday, March 20, 13
![Page 31: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/31.jpg)
AIDL• Previous examples work well for services
local to application.
• If you want to expose a service for other applications, you need an AIDL file.
package com.chaski.mobilemarchexample;
interface AIDLServiceaidl { int add(in int value1, in int value2, out int[] value3);}
AIDLServiceaidl.aidl
Looks just like an interface file!
31Wednesday, March 20, 13
![Page 32: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/32.jpg)
class AidlServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder boundService) { service = AIDLServiceaidl.Stub.asInterface((IBinder) boundService); Log.i(TAG, "onServiceConnected() connected"); }
public void onServiceDisconnected(ComponentName name) { service = null; Log.i(TAG, "onServiceDisconnected() disconnected"); } }
Connection looks nearly the same
32Wednesday, March 20, 13
![Page 33: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/33.jpg)
int res = 0; int[] value3 = new int[3]; try { res = service.add(1, 2, value3); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); }
AIDL Use is almost the same
Note: parameters can be used to pass data back
See AidlActivity.java
33Wednesday, March 20, 13
![Page 34: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/34.jpg)
What about implicit intents, leveraging other
peoples applications and reducing developer
burden?
34Wednesday, March 20, 13
![Page 35: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/35.jpg)
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(intent, 987654321);
protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == 987654321) { Bundle extras = intent.getExtras(); Bitmap bitmap = (Bitmap) extras.get("data"); } }
Lights Camera Action!
Request Code
Action
35Wednesday, March 20, 13
![Page 36: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/36.jpg)
intent = new Intent();intent.setAction(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_APP_EMAIL);
* In this example, we want an application that can handle email. We don’t care which one.
Implicit via category
36Wednesday, March 20, 13
![Page 37: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/37.jpg)
Implicit Intents
• Work from intent filters
• You can define your own
37Wednesday, March 20, 13
![Page 38: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/38.jpg)
intent = new Intent();intent.setAction(Intent.ACTION_MAIN);intent.addCategory("jeb");
* category is custom, named jeb! * Application that handles “jeb” needs this intent-filter in the manifest
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT"/> <category android:name="jeb"/></intent-filter>
You always need a default
ExampleImplicit via custom category
38Wednesday, March 20, 13
![Page 39: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/39.jpg)
Uri uri = Uri.parse("imdb:///find?q=godfather");intent = new Intent(android.content.Intent.ACTION_VIEW, uri);startActivity(intent);
ExampleImplicit Intent via URI
Action
Data
39Wednesday, March 20, 13
![Page 40: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/40.jpg)
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="ted"/>
</intent-filter>
Intent sender code: Uri uri = Uri.parse("ted:");intent = new Intent(android.content.Intent.ACTION_VIEW, uri);startActivity(intent);
Our Custom URI
ExampleImplicit Intent via Custom URI
40Wednesday, March 20, 13
![Page 41: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/41.jpg)
<activity android:name=".MainActivity" android:label="@string/title_activity_main" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
<intent-filter> <action android:name="com.chaski.ButtonCatcher.catch" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.APP_EMAIL"/> </intent-filter> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT"/> <category android:name="jeb"/> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="ted"/> </intent-filter> </activity>
Intent filters are loaded into Manifest
Custom Intents
41Wednesday, March 20, 13
![Page 42: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/42.jpg)
UR’all that… and more!iOS Inter-App Communication
• Launching apps automatically via URLs
• Providing services from your app
• Sending values and returning results
• Standardizing interfaces with x-callback-url
42Wednesday, March 20, 13
![Page 43: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/43.jpg)
“Launching” AppsManually
• “Launching” from user context
• App startup after install, power-up, kill, jettison, crash
• Returning from background
• Spring board (a.k.a Home Screen)
• Tap app icon
• Dock, Folders & Multitasking Bar
• “Search iPhone”
• Siri
• Hold Home button and say app name
43Wednesday, March 20, 13
![Page 44: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/44.jpg)
Launching AppsAutomatically
• URL schemes
• E.g., http://www.w3schools.com/ fb://friends
• Document/file type support
• Local notifications
• Push notifications
44Wednesday, March 20, 13
![Page 45: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/45.jpg)
Data Sharingvia Network
• Cloud service
• E.g., Facebook, DropBox, proprietary
• Allows non-iOS device and browser access
• iCloud
• Game Center
• Push notifications
45Wednesday, March 20, 13
![Page 46: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/46.jpg)
Data Sharingon Device
• URL parameters
• E.g., http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino
• Keychain Services
• Document/file type support
• Pasteboards
• Core Audio
• Core MIDI
46Wednesday, March 20, 13
![Page 47: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/47.jpg)
AppleURL Schemes
Safari http://www.yahoo.com https://www.wellsfargo.com
Mail mailto:[email protected]
Phone tel:1-408-555-5555
Text sms:1-408-555-1212
Maps http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino
YouTube http://www.youtube.com/watch?v=2DSrJXQV9Og
iTunes http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?i=156093464&id=156093462&s=143441
47Wednesday, March 20, 13
![Page 48: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/48.jpg)
In-App ServicesNative API
Safari UIWebView
Mail MFMailComposeViewController
Phone
Text MFMessageComposeViewController
Map MKMapView
YouTube UIWebView
iTunes
48Wednesday, March 20, 13
![Page 49: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/49.jpg)
Launching App viaHTML Link
• HTML links<a href="tel:1-408-555-5555">Call your representative</a>
• Safari and Email apps
• UIWebView
49Wednesday, March 20, 13
![Page 50: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/50.jpg)
LinkAuto-Detection
• Auto-detection of link-like text within HTML
• Telephone numbers
• URLs
• Parse-able strings containing “://”
• Missing “http://” prefix
50Wednesday, March 20, 13
![Page 51: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/51.jpg)
Launching app viaNative API
• Objective-C APIUIApplication -canOpenURL:
UIApplication -openURL:
• ExampleNSURL *url = [NSURL URLWithString:@"tel:1-408-555-5555"];
if([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url];
}
51Wednesday, March 20, 13
![Page 52: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/52.jpg)
Custom URL Schemes• Not cutting edge, but not always well-executed
• Many apps provide a “noun” to launch them yelp4://
flixter://
angrybirds-free://
angrybirds-hd-free://
• Fewer apps provide “verbs” to control themyelp:///search?terms=bars&location=sf
52Wednesday, March 20, 13
![Page 53: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/53.jpg)
Custom URL SchemeExample
googlechrome: Launches Chrome app
googlechrome://www.yahoo.com Opens new tab and navigates to http://www.yahoo.com
googlechromes://www.wellsfargo.com Similar to https:
googlechrome-x-callback://x-callback-url/open?
x-success=myscheme%3A%2F%2F&
x-source=MyApp&
url=http%3A%2F%2Fwww.yahoo.com
Specifies display name and scheme of app for return
53Wednesday, March 20, 13
![Page 54: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/54.jpg)
Discovering Schemes• iHasApp open source framework
• Correlates Schemes and app IDs
• schemeApps.json{ ...
"googlechrome": [535886823],
"googlechromes": [535886823],
"googledrive": [507874739],
"googlegmail": [422689480],
...
"yelp4.2": [284910350],
"yelp4.4": [284910350],
... }
54Wednesday, March 20, 13
![Page 55: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/55.jpg)
App IDs• iTunes Preview
https://itunes.apple.com/us/app/chrome/id535886823?mt=8
• Look up
http://itunes.apple.com/lookup?id=535886823
Returns JSON
"trackId":535886823,
"trackName":"Chrome"
"artworkUrl60":"http://a1619.phobos.apple.com/us/r1000/064/Purple2/v4/96/8d/ce/968dcef9-32d8-bf0b-2e86-a1c0e75c61af/Icon.png",
55Wednesday, March 20, 13
![Page 56: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/56.jpg)
Scheme “Actions”
• handleOpenURL website
• Search scheme index
skype:thurston.howell.iii?call
skype://lovey?chat
56Wednesday, March 20, 13
![Page 57: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/57.jpg)
Schemes to the Extreme• akosma software web page
• URL encoding tips
CFURLCreateStringByAddingPercentEscapes()
preferred over
NSString -stringByAddingPercentEscapesUsingEncoding:
• Undocumented(?) Apple URL schemes
• Google Maps, Music, Videos, App Store, iBooks, iBooks Store, Podcasts
• Safer: comgooglemaps://
• Objective-C code examples
57Wednesday, March 20, 13
![Page 58: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/58.jpg)
“App Launcher” Apps• Launch Center Pro
• Launch+
• Quickpick
• Launcher
• Speed U
• App Gate
• Simple Launcher
• Simple Phone Launcher
• Swipemint
58Wednesday, March 20, 13
![Page 59: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/59.jpg)
• Pre-canned schemes & actions
• Detection of installed apps
• Links to App Store
• Custom URLs
• Clipboard or user prompt
• In app for iOS features
• Access to non-scheme iOS features
• Scheduled notifications
• Organize favorites
• Icon management
• Download new URLs
• Uni-directional; no return
"App Launcher"Typical Features
59Wednesday, March 20, 13
![Page 60: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/60.jpg)
Your very ownURL scheme
• Choosing a “unique” scheme name
• No official master list beyond IANA
• Priority among conflicts undefined
• Cannot override Apple schemes
• “googlechrome:” instead of “chrome:”
• Search unofficial sources and “advertise” your own scheme!
60Wednesday, March 20, 13
![Page 61: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/61.jpg)
Registering Schemewith iOS
• E.g., myApp-Info.plist
<key>CFBundleURLTypes</key>
<array>
! <dict>
! ! <key>CFBundleURLName</key>
! ! <string>com.mydomain.myapp</string>
! ! <key>CFBundleURLSchemes</key>
! ! <array>
! ! ! <string>myscheme</string>
! ! </array>
! </dict>
</array>
61Wednesday, March 20, 13
![Page 62: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/62.jpg)
Handling Received URL
• Delegate callback APIUIApplicationDelegate -application:openURL:sourceApplication:annotation:
• Example- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSLog(@"%@", [url absoluteString]);
return YES;
}
62Wednesday, March 20, 13
![Page 63: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/63.jpg)
“Parsing” the URL
• Call component methods on(NSURL *)url
[url scheme] NSString *theScheme = [url scheme]
[url user] "
[url password] "
[url host]
[url port] NSNumber *thePort = [url port]
[url path]
[url parameterString]
[url query]
[url fragment]
63Wednesday, March 20, 13
![Page 64: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/64.jpg)
App Startup• A.k.a. “launching” vs. returning from background
• Delegate callback APIUIApplicationDelegate -application:didFinishLaunchingWithOptions:
• Example- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURL *url = [launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
NSLog(@"%@", [url absoluteString]);
return YES; // Allow openURL to run
}
64Wednesday, March 20, 13
![Page 65: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/65.jpg)
Smart App Banners• Displays promotional banner on web page
<meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">
Offers to take user to App or App Store as appropriate
• E.g., “LinkedIn Connections” email on iPhone
• Tapping button opens Safari “Sign in” page
• If LinkedIn app is installed, banner appears offering to “OPEN” it
• Tapping OPEN opens app
65Wednesday, March 20, 13
![Page 66: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/66.jpg)
Return to Sender
• Facebook scheme format:
fb<ID>: E.g. , fb165260790249214:
• Google Chrome (as seen earlier)googlechrome-x-callback://x-callback-url/
• Terminology thesaurus lookup & selectionterminology://x-callback-url/
66Wednesday, March 20, 13
![Page 67: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/67.jpg)
x-callback-url
• Encourages services that perform and return
• Standardizes service API structure
• Format and URL encoding
• Inter-App Communication (IAC)
• Taps & Swipes open source framework
67Wednesday, March 20, 13
![Page 68: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/68.jpg)
How it Works
Client Server
theserverscheme:...?aclientscheme:...aclienttarget...
aclientscheme:.../aclienttarget?theserverparameters
NeedIt
GotIt
DoingIt
• App “launch” via URL scheme used for both directions
• Server defines well-known scheme and service
• Client specifies return scheme & delegates
68Wednesday, March 20, 13
![Page 69: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/69.jpg)
Service API Structure[scheme]://[host]/[action]?[x-callback parameters]&[action parameters]
• host x-callback-url
• x-callback query parameters
• App display name x-source
• Success delegate x-success
• Error delegate x-error
• Cancel delegate x-cancel
69Wednesday, March 20, 13
![Page 70: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/70.jpg)
Terminology App
• Legacy lookupterminology://heavy
• Modern, but no return requestedterminology://x-callback-url/lookup?text=heavy
70Wednesday, March 20, 13
![Page 71: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/71.jpg)
TerminologyReturn Result
• Request return (unencoded)terminology://x-callback-url/replace?
x-success=myscheme://x-callback-url/myReturnAction& x-source=MyAppName&
text=heavy
• Return Resultmyscheme://x-callback-url/myReturnAction?
text=heavy&
replaceWith=dense&
71Wednesday, March 20, 13
![Page 72: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/72.jpg)
URL Encoding• Basic URL encoding
terminology://x-callback-url/lookup?text=heavy%20metal
• URL query parameters specify URLsterminology://x-callback-url/replace?
x-success=myscheme://x-callback-url/myReturnAction& x-source=MyAppName&
text=heavy
• Must encode these nested URLsterminology://x-callback-url/replace?
x-success=myscheme%3A%2F%2Fx-callback-url%2FmyReturnAction&
x-source=MyAppName&
text=heavy
72Wednesday, March 20, 13
![Page 73: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/73.jpg)
Demo
• XCallbackURL open source test app
Replace “Heavy”
Replace with “Dense”
73Wednesday, March 20, 13
![Page 74: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/74.jpg)
Just when your ‘intent’ was to go back into the
water!
74Wednesday, March 20, 13
![Page 75: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/75.jpg)
• Unauthorized Intent Receipt
• Broadcast Theft
• Activity Hijacking
• Service Hijacking
• Intent Spoofing
• Malicious Broadcast Injection
Intent-Based Attacks
75Wednesday, March 20, 13
![Page 76: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/76.jpg)
Unauthorized Intent Reception
• Broadcast Theft
• Eavesdropper can silently read contents of a broadcast without interrupting broadcast
• Attacker could launch denial of service or data injection attack
• Ordered Broadcasts can be subject to
76Wednesday, March 20, 13
![Page 77: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/77.jpg)
• Malicious Broadcast Injection
• Malicious Activity Launch
• Malicious Service Launch
Intent Spoofing
77Wednesday, March 20, 13
![Page 78: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/78.jpg)
How hard is this?
• apktool
• https://code.google.com/p/android-apktool/
• dare
• http://siis.cse.psu.edu/dare/index.html
78Wednesday, March 20, 13
![Page 79: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/79.jpg)
How hard?•Get apktool.jar
•https://code.google.com/p/android-apktool/
•Get your apk files
•java -r apktool.jardecode ..
79Wednesday, March 20, 13
![Page 80: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/80.jpg)
Text
Look at that!Our manifest, our resources.
Oh the humanity!
80Wednesday, March 20, 13
![Page 81: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/81.jpg)
Security
• Don’t mess with peoples data if you don’t have to.
• When sending private data, use explicit intents
• Internal Intents should always be explicit!
• Strong permissions be used. As strong as possible.
• Review signature permissions
81Wednesday, March 20, 13
![Page 82: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/82.jpg)
iOS Scheme Security
• URLs inherently insecure
• No HTTPS equivalent
82Wednesday, March 20, 13
![Page 83: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/83.jpg)
Hacking URL schemes
• iOS handling of duplicates
• Masquerading as client
• Masquerading as server
• Misrouting callbacks
• Discovering schemes
• Discovering apps
• Non-App Store hacking tools
83Wednesday, March 20, 13
![Page 84: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/84.jpg)
What can be done?• Encrypt URL after scheme: (or schemes:// ?)
• Shared secret
• Public key cryptography
• Encrypted data must be “URL parseable” by iOS and URL encoded
• Send encrypted data out of band
• E.g., iOS Keychain Services
• Shared keychain
84Wednesday, March 20, 13
![Page 85: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/85.jpg)
Keychain Services
• Create Entitlements.plist
• Add keychain-access-group
• ANSI C APICFDictionaryRef bridged from NSMutableDictionary
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result)
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result)
85Wednesday, March 20, 13
![Page 86: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/86.jpg)
Huh?
I have just one question...
86Wednesday, March 20, 13
![Page 87: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/87.jpg)
Thank you!
On the Android banjo and security mandolin:
On the iOS banjo and network protocol fiddle:
Michael Dorin [email protected] www.linkedin.com/in/michaeldorin
Dan Ratcliff [email protected] http://www.linkedin.com/in/danratcliff
87Wednesday, March 20, 13
![Page 88: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/88.jpg)
Sources• Stackoverflow
• http://stackoverflow.com
• Android Developers Guide• http://developer.android.com/guide
• Intent and Intent Filters, by Sang Shin and Michèle Garoche • http://documents.cofares.net/miroires/AndroidPourValeurC/8-android_intent.pdf
• Systems and Internet Infrastructure Security, Dare• http://siis.cse.psu.edu/dare/installation.html
• Analyzing Inter-Application Communication in Android• http://www.cs.berkeley.edu/~afelt/intentsecurity-mobisys.pdf
88Wednesday, March 20, 13
![Page 89: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/89.jpg)
Sources• Apple URL Scheme Reference
• http://developer.apple.com/library/ios/#featuredarticles/iPhoneURLScheme_Reference/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40007891-SW1
• Communicating with Other Apps• http://developer.apple.com/library/ios/#documentation/iphone/conceptual/
iphoneosprogrammingguide/AdvancedAppTricks/AdvancedAppTricks.html
• iPhone Apps | Yelp for Developers• http://www.yelp.com/developers/documentation/iphone
• Opening Links in Chrome for iOS• https://developers.google.com/chrome/mobile/docs/ios-links
89Wednesday, March 20, 13
![Page 90: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/90.jpg)
Sources• iHasApp - Installed App Detection
• http://www.ihasapp.com
• handleOpenURL: Shared App Communication on iOS• http://handleopenurl.com
• Skype URI Handler• http://dev.skype.com/desktop-api-reference#URI
• IPhone URL Schemes - akosma wiki• http://wiki.akosma.com/IPhone_URL_Schemes
• Google's New iOS Maps App and URL Scheme• http://www.pureoxygenmobile.com/googles-new-maps-ios-app-and-url-scheme/
90Wednesday, March 20, 13
![Page 91: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/91.jpg)
Sources• Launch Center Pro
• https://itunes.apple.com/us/app/launch-center-pro/id532016360?mt=8
• Launch+• https://itunes.apple.com/us/app/launch+/id500606931?mt=8
• Quickpick• http://www.neoos.ch/https://itunes.apple.com/us/app/id483079724/quickpick
• Launcher• https://itunes.apple.com/us/app/launcher-quick-actions-shortcuts!/id511645204?
mt=8
• Speed U• https://itunes.apple.com/us/app/speed-u/id510914771?mt=8
91Wednesday, March 20, 13
![Page 92: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/92.jpg)
Sources• App Gate
• https://itunes.apple.com/us/app/app-gate./id566901497?mt=8
• Simple Launcher• https://itunes.apple.com/us/app/simple-launcher-for-ipad-launch/id467950393?
mt=8&ign-mpt=uo%3D2
• Simple Phone Launcher• https://itunes.apple.com/hk/app/simple-phone-launcher-launch/id430233514?mt=8
• Swipemint• https://itunes.apple.com/us/app/swipemint-fastest-simple-launcher/id540044893?
mt=8
• URI Scheme• http://en.wikipedia.org/wiki/URI_scheme
92Wednesday, March 20, 13
![Page 93: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/93.jpg)
Sources• Promoting Apps with Smart App Banners
• http://developer.apple.com/library/ios/#documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
• Share an App ID Across Apps - Facebook Developers• http://developers.facebook.com/docs/howtos/share-appid-across-multiple-apps-ios-
sdk/
• Terminology Developers - Agile Tortoise• http://agiletortoise.com/terminology-developers/
• Opening Links in Chrome for iOS• https://developers.google.com/chrome/mobile/docs/ios-links
93Wednesday, March 20, 13
![Page 94: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/94.jpg)
Sources• x-callback-url
• http://x-callback-url.com
• tapsandswipes/InterAppCommunication - GitHub• https://github.com/tapsandswipes/InterAppCommunication
• Taps and Swipes• http://tapsandswipes.com
• Terminology• https://itunes.apple.com/us/app/terminology/id380288546?mt=8
• agiletortoise/XCallbackURL - GitHub• https://github.com/agiletortoise/XCallbackURL
94Wednesday, March 20, 13
![Page 95: Dueling Banjos: Inter-app Communication](https://reader034.vdocuments.site/reader034/viewer/2022052315/554a1f8db4c90507558b5a2d/html5/thumbnails/95.jpg)
Sources• iOS Keychain: Sharing data between apps
• http://shaune.com.au/ios-keychain-sharing-data-between-apps/
• Keychain Services Programming Guide• https://developer.apple.com/library/ios/#documentation/security/conceptual/
keychainServConcepts/iPhoneTasks/iPhoneTasks.html%23//apple_ref/doc/uid/TP30000897-CH208-SW1
• Audiobus• http://audiob.us
• Dueling Banjos• http://www.youtube.com/watch?v=Vj9ghC2SgbY
95Wednesday, March 20, 13