SlideShare uma empresa Scribd logo
1 de 22
Valerio “Lotti” Riva – Interactive Project
valerio.riva@gmail.com
@ValerioRiva
http://it.linkedin.com/in/valerioriva/
Avoid loss of hair while coding
Unity3D plugins for mobile
ROME 24 June 2014 – Valerio Riva
Codemotion Tech Meetup #4 – Roma Summer Edition
Nice to meet you!
• Web / Game developer
• Recent works @ Interactive Project
• World Cup Juggler
• OverVolt: crazy slot cars
ROME 24 June 2014 – Valerio Riva
2
Why develop a Unity3D mobile plugin?
• Access to device native features
• Implement third-party SDK (analytics, advertising,
in-app purchases, game services, etc.)
• Save/Earn money
• Personal growth
ROME 24 June 2014 – Valerio Riva
3
Extending Unity 4.x
• Unity supports C/C++ libraries. “extern”-alized
functions/methods can be called from C#
• All plugins must be placed inside “Assets/Plugins”
folder
• Platform-dependent plugins must be placed inside
specific folders (x86, x86_64, Android, iOS, WP8, Metro,
etc.)
• Available only on Unity3D Pro/Mobile
ROME 24 June 2014 – Valerio Riva
4
Extending Unity (iOS)
• Call externalized Object-C methods
• Must wraps third-party SDK if their methods are not
externalized
• Gameobjects can receive messages from native code
• Receiver methods declared on GO’s components must
have only 1 string parameter as signature
ROME 24 June 2014 – Valerio Riva
5
Extending Unity (Android)
• Use JNI (Java Native Interface), Unity provides Helper
classes
• Call native methods directly from Unity
• Gameobjects can receive messages from native code
• Receiver methods declared on GO’s components must have
only 1 string parameter as signature
• On specific cases, Unity Player activity must be extended
• Android Manifest editing is often required
ROME 24 June 2014 – Valerio Riva
6
Extending Unity (WP8)
• Access native code directly from Unity
• Use of callbacks to return data from native code
• Unity’s Mono (v2.6) doesn’t support .NET >= 4.0
• Artefacts are needed to use .NET >= 4.0 libaries
• “Always” needs a fake and a real plugin – Unity will
overwrite fake one with the real one automatically
• In specific cases, write a plugin is a monkey job
ROME 24 June 2014 – Valerio Riva
7
Extending Unity (remarks)
• Scripting define symbols are your friends
• Native calls are CPU intensive
• Provide fake results for in-editor usage
• Every native UI call must run inside native UI thread
• Every callback must run inside Unity thread (WP8)
• Save time by testing plugin on a native app
• Remember to include Unity library if needed
• classes.jar
• UnityEngine.dll
ROME 24 June 2014 – Valerio Riva
8
Case study: Flurry plugin
• Wrap Flurry SDK to made it accessible from Unity
• Flurry SDK is simple to use, just call static methods
(Advertising, In-App Purchase, …, are more complex plugin)
• We have to code wrappers for each platform
• Place platforms SKDs on the right directories
• FlurryAnalytics-4.0.0.jar -> Plugins/Android/
• libFlurry_5.0.0.a -> Plugins/iOS/
• FlurryWP8SDK.dll -> Plugins/WP8/
• FlurryWP8SDK.dll -> Plugins/ (the WP8 fake one)
ROME 24 June 2014 – Valerio Riva
9
Flurry plugin (iOS)
• Flurry SDK is not “extern”-alized
• Dictionary<string, string> must be translated somewhat to
NSMutableDictionary
• Each KeyValuePair<string,string> are concatenated to form a single
string
ROME 24 June 2014 – Valerio Riva
10
//FlurryiOS.h - created by PRADA Hsiung on 13/3/8.
extern "C" {
void FlurryiOS_startSession(unsigned char* apiKey);
void FlurryiOS_setEventLoggingEnabled(BOOL bEnabled);
void FlurryiOS_logEventWithParameters(unsigned char* eventId,unsigned
char *parameters);
}
Flurry plugin (iOS)
// FlurryiOS.m - created by Faizan Naqvi on 1/10/13.
#import <stdio.h>
#include "Flurry.h" //Flurry SDK headers
void FlurryiOS_startSession(const char* apiKey) {
NSString *str = [NSString stringWithUTF8String:apiKey];
[Flurry startSession:str];
}
void FlurryiOS_setEventLoggingEnabled(BOOL bEnabled){
[Flurry setEventLoggingEnabled:bEnabled];
}
ROME 24 June 2014 – Valerio Riva
11
Flurry plugin (iOS)
void FlurryiOS_logEventWithParameters(const char* eventId,const char *parameters) {
NSString *params = [NSString stringWithUTF8String:parameters];
NSArray *arr = [params componentsSeparatedByString: @"n"];
NSMutableDictionary *pdict = [[[NSMutableDictionary alloc] init] autorelease];
for(int i=0;i < [arr count]; i++) {
NSString *str1 = [arr objectAtIndex:i];
NSRange range = [str1 rangeOfString:@"="];
if (range.location!=NSNotFound) {
NSString *key = [str1 substringToIndex:range.location];
NSString *val = [str1 substringFromIndex:range.location+1];
//NSLog(@"kv %@=%@n",key,val);
[pdict setObject:val forKey:key];
} }
if([pdict count]>0) {
[Flurry logEvent:[NSString stringWithUTF8String:eventId] withParameters:pdict timed:false];
} else FlurryiOS_logEvent(eventId);
}
ROME 24 June 2014 – Valerio Riva
12
Flurry plugin (iOS)
Meanwhile on Unity side…
#region FlurryiOS_Imports
[DllImport("__Internal", CharSet = CharSet.Ansi)]
private static extern void FlurryiOS_startSession([In, MarshalAs(UnmanagedType.LPStr)]string
apiKey);
[DllImport("__Internal")]
private static extern void FlurryiOS_setEventLoggingEnabled(bool bEnabled);
[DllImport("__Internal", CharSet = CharSet.Ansi)]
private static extern void FlurryiOS_logEventWithParameters([In,
MarshalAs(UnmanagedType.LPStr)]string evendId, [In,
MarshalAs(UnmanagedType.LPStr)]string parameters);
#endregion
ROME 24 June 2014 – Valerio Riva
13
Flurry plugin (WP8)
• Flurry SDK is compiled with .NET 4.5, import it and Unity will go
mad!
• We need the “fake & real” library approach, but…
• Using Flurry SDK doesn’t involve use of complex logic or complex
user defined classes…
• … we can use the downloaded FlurryWP8SDK.dll as “real”
• and code only the fake dll!
Yes, this is the particular case
where you can bring in monkeys!
ROME 24 June 2014 – Valerio Riva
14
Flurry plugin (WP8)
using FlurryWP8SDK.Models;
using System;
using System.Collections.Generic;
namespace FlurryWP8SDK.Models {
public enum Gender { Unknown = -1, Female = 0, Male = 1 }
public class Parameter {
public Parameter(string name, string value) {
Name = name;
Value = value;
}
public string Name { get; set; }
public string Value { get; set; }
}
}
namespace FlurryWP8SDK {
public sealed class Api {
private static Api instance = null;
public static Api Current { get { return instance; } }
public void DummyInitiator() {}
public static void EndSession() {}
public static void EndTimedEvent(string eventName) {}
public static void EndTimedEvent(string eventName, List<Parameter> parameters) {}
public static void LogEvent(string eventName) {}
public static void LogEvent(string eventName, List<Parameter> parameters, bool timed) {}
public static void SetAge(int age) {}
public static void SetGender(Gender gender) {}
public static void SetLocation(double latitude, double longitude, float accuracy) {}
public static void SetSessionContinueSeconds(int seconds) {}
public static void StartSession(string apiKey) {}
}
}
ROME 24 June 2014 – Valerio Riva
15
That was easy, now
give me peanuts!
Flurry plugin (Android)
• As said before, Flurry doesn’t involve complex logic…
• … so we save time and wrote plugin directly in Unity using JNI
Helper classes
ROME 24 June 2014 – Valerio Riva
16
public Flurry StartSession(string apiKey) {
#if !UNITY_EDITOR && UNITY_WP8
Api.StartSession(apiKey);
#elif !UNITY_EDITOR && UNITY_ANDROID
using(AndroidJavaClass cls_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using(AndroidJavaObject obj_Activity = cls_UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
using(AndroidJavaClass cls_FlurryAgent = new AndroidJavaClass("com.flurry.android.FlurryAgent")) {
cls_FlurryAgent.CallStatic("onStartSession", obj_Activity, apiKey);
}
#elif !UNITY_EDITOR && UNITY_IPHONE
FlurryiOS_startSession(apiKey);
#endif
return this;
}
Flurry plugin (Android)
ROME 24 June 2014 – Valerio Riva
17
public Flurry LogEvent(string eventId, Dictionary<string,string> parameters, bool timed) {
#if !UNITY_EDITOR && UNITY_WP8
List<Parameter> p = new List<Parameter>();
foreach(KeyValuePair<string,string> i in parameters) {
p.Add(new Parameter(i.Key,i.Value));
}
Api.LogEvent(eventId, p, timed);
#elif !UNITY_EDITOR && UNITY_ANDROID
using(AndroidJavaObject obj_HashMap = new AndroidJavaObject("java.util.HashMap")) {
// Call 'put' via the JNI instead of using helper classes to avoid: "JNI: Init'd AndroidJavaObject with null ptr!"
IntPtr method_Put = AndroidJNIHelper.GetMethodID(obj_HashMap.GetRawClass(), "put“,
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
object[] args = new object[2];
foreach(KeyValuePair<string, string> kvp in parameters) {
using(AndroidJavaObject k = new AndroidJavaObject("java.lang.String", kvp.Key))
using(AndroidJavaObject v = new AndroidJavaObject("java.lang.String", kvp.Value)) {
args[0] = k;
args[1] = v;
AndroidJNI.CallObjectMethod(obj_HashMap.GetRawObject(), method_Put, AndroidJNIHelper.CreateJNIArgArray(args));
}
}
cls_FlurryAgent.CallStatic("logEvent", eventId, obj_HashMap, timed);
}
#elif !UNITY_EDITOR && UNITY_IPHONE
FlurryiOS_logEventWithParametersTimed(eventId, dictionaryToText(parameters));
#endif
return this;
}
and for more complex plugins…?
• Do most of logic on native side to minimize native calls from Unity
• Messages examples (Android)
UnityPlayer.UnitySendMessage("gameObjectName", "methodName", "message");
• Use “Action<…>” delegates to pass callbacks on WP8, Unity supports
Action with max 4 parameters as .NET 3.5 does
• Structure plugin as a wrapper (mainly for third-party SDKs)
• Hide user defined classes (e.g.: instantiate them with methods) so Unity can’t see
them
• Wrap API calls with ones that use just primitive or built-in data type and the convert
them to user defined classes inside plugin!
ROME 24 June 2014 – Valerio Riva
18
Run on UI Thread
• iOS
dispatch_async(dispatch_get_main_queue(), ^{
// Your code to run on the main queue/thread
});
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Your code to run on the main queue/thread
}];
• Android
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
public void run() {
//your code to run on the UI thread
}
});
ROME 24 June 2014 – Valerio Riva
19
Run on UI Thread (WP8)
• MainPage.xaml.cs
public partial class MainPage : PhoneApplicationPage
{
public void InvokeOnAppThread ( Action callback ) {
UnityApp.BeginInvoke ( () => { callback (); } );
}
public void InvokeOnUIThread ( Action callback ) {
Dispatcher.BeginInvoke ( () => { callback (); } );
}
private void Unity_Loaded() {
…
MyDispatcher.InvokeOnAppThread = InvokeOnAppThread;
MyDispatcher.InvokeOnUIThread = InvokeOnUIThread;
…
}
}
• MyPlugin.cs
MyDispatcher.InvokeOnAppThread(() => {
//your Unity callbacks execution must be placed here
});
MyDispatcher.InvokeOnUIThread(() => {
//your code to run on UI Thread
});
ROME 24 June 2014 – Valerio Riva
20
Resources and examples
Resources
• http://docs.unity3d.com/Manual/Plugins.html
• http://docs.unity3d.com/Manual/wp8-plugins.html
• http://docs.unity3d.com/Manual/PluginsForAndroid.html
• http://docs.unity3d.com/Manual/PluginsForIOS.html
Examples
• https://github.com/playgameservices/play-games-plugin-for-unity
• https://github.com/googleads/googleads-mobile-
plugins/tree/master/unity
• https://github.com/guillermocalvo/admob-unity-plugin
• https://github.com/mikito/unity-admob-plugin
• https://github.com/bearprada/flurry-unity-plugin
• https://github.com/mikito/unity-flurry-plugin
• https://github.com/faizann/unity3d_flurry
ROME 24 June 2014 – Valerio Riva
21
Thank you!
ROME 24 June 2014 – Valerio Riva
22
Question Time
No animals were harmed in the making of this talk
valerio.riva@gmail.com
@ValerioRiva
http://it.linkedin.com/in/valerioriva/

Mais conteúdo relacionado

Mais procurados

Using Pin++ to Author Highly Configurable Pintools for Pin
Using Pin++ to Author Highly Configurable Pintools for PinUsing Pin++ to Author Highly Configurable Pintools for Pin
Using Pin++ to Author Highly Configurable Pintools for PinJames Hill
 
Con-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistCon-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistAnton Arhipov
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and DevelopmentOpersys inc.
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and DevelopmentKarim Yaghmour
 
DBI-Assisted Android Application Reverse Engineering
DBI-Assisted Android Application Reverse EngineeringDBI-Assisted Android Application Reverse Engineering
DBI-Assisted Android Application Reverse EngineeringSahil Dhar
 
LicensePlist - A license list generator of all your dependencies for iOS appl...
LicensePlist - A license list generator of all your dependencies for iOS appl...LicensePlist - A license list generator of all your dependencies for iOS appl...
LicensePlist - A license list generator of all your dependencies for iOS appl...将之 小野
 
Metasepi team meeting #6: "Snatch-driven development"
Metasepi team meeting #6: "Snatch-driven development"Metasepi team meeting #6: "Snatch-driven development"
Metasepi team meeting #6: "Snatch-driven development"Kiwamu Okabe
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and DevelopmentOpersys inc.
 
Embedded Android Workshop with Marshmallow
Embedded Android Workshop with MarshmallowEmbedded Android Workshop with Marshmallow
Embedded Android Workshop with MarshmallowOpersys inc.
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and DevelopmentOpersys inc.
 
Developing Android Platform Tools
Developing Android Platform ToolsDeveloping Android Platform Tools
Developing Android Platform ToolsOpersys inc.
 
Native code in Android applications
Native code in Android applicationsNative code in Android applications
Native code in Android applicationsDmitry Matyukhin
 
Running TFLite on Your Mobile Devices, 2020
Running TFLite on Your Mobile Devices, 2020Running TFLite on Your Mobile Devices, 2020
Running TFLite on Your Mobile Devices, 2020Koan-Sin Tan
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and DevelopmentOpersys inc.
 
FRIDA 101 Android
FRIDA 101 AndroidFRIDA 101 Android
FRIDA 101 AndroidTony Thomas
 

Mais procurados (20)

Android ndk: Entering the native world
Android ndk: Entering the native worldAndroid ndk: Entering the native world
Android ndk: Entering the native world
 
Using Pin++ to Author Highly Configurable Pintools for Pin
Using Pin++ to Author Highly Configurable Pintools for PinUsing Pin++ to Author Highly Configurable Pintools for Pin
Using Pin++ to Author Highly Configurable Pintools for Pin
 
Con-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistCon-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With Javassist
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and Development
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and Development
 
DBI-Assisted Android Application Reverse Engineering
DBI-Assisted Android Application Reverse EngineeringDBI-Assisted Android Application Reverse Engineering
DBI-Assisted Android Application Reverse Engineering
 
LicensePlist - A license list generator of all your dependencies for iOS appl...
LicensePlist - A license list generator of all your dependencies for iOS appl...LicensePlist - A license list generator of all your dependencies for iOS appl...
LicensePlist - A license list generator of all your dependencies for iOS appl...
 
Metasepi team meeting #6: "Snatch-driven development"
Metasepi team meeting #6: "Snatch-driven development"Metasepi team meeting #6: "Snatch-driven development"
Metasepi team meeting #6: "Snatch-driven development"
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and Development
 
Couverture de code
Couverture de codeCouverture de code
Couverture de code
 
Embedded Android Workshop with Marshmallow
Embedded Android Workshop with MarshmallowEmbedded Android Workshop with Marshmallow
Embedded Android Workshop with Marshmallow
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and Development
 
Developing Android Platform Tools
Developing Android Platform ToolsDeveloping Android Platform Tools
Developing Android Platform Tools
 
A Peek into TFRT
A Peek into TFRTA Peek into TFRT
A Peek into TFRT
 
Native code in Android applications
Native code in Android applicationsNative code in Android applications
Native code in Android applications
 
Android JNI
Android JNIAndroid JNI
Android JNI
 
Running TFLite on Your Mobile Devices, 2020
Running TFLite on Your Mobile Devices, 2020Running TFLite on Your Mobile Devices, 2020
Running TFLite on Your Mobile Devices, 2020
 
Android Platform Debugging and Development
Android Platform Debugging and DevelopmentAndroid Platform Debugging and Development
Android Platform Debugging and Development
 
Android Internals
Android InternalsAndroid Internals
Android Internals
 
FRIDA 101 Android
FRIDA 101 AndroidFRIDA 101 Android
FRIDA 101 Android
 

Semelhante a Avoid loss of hair while coding Unity3D plugins for mobile

Python Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIPython Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIBruno Rocha
 
Cross platform mobile apps using .NET
Cross platform mobile apps using .NETCross platform mobile apps using .NET
Cross platform mobile apps using .NETJonas Follesø
 
NSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine Security
NSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine SecurityNSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine Security
NSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine SecurityNoSuchCon
 
Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)Eugenio Minardi
 
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Christian Schneider
 
Appium Overview - by Daniel Puterman
Appium Overview - by Daniel PutermanAppium Overview - by Daniel Puterman
Appium Overview - by Daniel PutermanApplitools
 
EuroPython 2014 - How we switched our 800+ projects from Apache to uWSGI
EuroPython 2014 - How we switched our 800+ projects from Apache to uWSGIEuroPython 2014 - How we switched our 800+ projects from Apache to uWSGI
EuroPython 2014 - How we switched our 800+ projects from Apache to uWSGIMax Tepkeev
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesPavol Pitoňák
 
Porting your favourite cmdline tool to Android
Porting your favourite cmdline tool to AndroidPorting your favourite cmdline tool to Android
Porting your favourite cmdline tool to AndroidVlatko Kosturjak
 
Rapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
Rapid Prototyping Chatter with a PHP/Hack Canvas App on HerokuRapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
Rapid Prototyping Chatter with a PHP/Hack Canvas App on HerokuSalesforce Developers
 
Setting Apple's UI Automation Free with Appium
Setting Apple's UI Automation Free with AppiumSetting Apple's UI Automation Free with Appium
Setting Apple's UI Automation Free with Appiummobiletestsummit
 
Custom Buildpacks and Data Services
Custom Buildpacks and Data ServicesCustom Buildpacks and Data Services
Custom Buildpacks and Data ServicesTom Kranz
 
Create a-strong-two-factors-authentication-device-for-less-than-chf-100
Create a-strong-two-factors-authentication-device-for-less-than-chf-100Create a-strong-two-factors-authentication-device-for-less-than-chf-100
Create a-strong-two-factors-authentication-device-for-less-than-chf-100Cyber Security Alliance
 
Native Javascript apps with Phonegap - De Keijzer
Native Javascript apps with Phonegap - De KeijzerNative Javascript apps with Phonegap - De Keijzer
Native Javascript apps with Phonegap - De KeijzerCodemotion
 
Native Javascript apps with PhoneGap 11-04-2014 Codemotion Rome
Native Javascript apps with PhoneGap 11-04-2014 Codemotion RomeNative Javascript apps with PhoneGap 11-04-2014 Codemotion Rome
Native Javascript apps with PhoneGap 11-04-2014 Codemotion RomeMartin de Keijzer
 
Flutter Forward EXTENDED - Flutter로 앱 개발 입문하기
Flutter Forward EXTENDED -  Flutter로 앱 개발 입문하기Flutter Forward EXTENDED -  Flutter로 앱 개발 입문하기
Flutter Forward EXTENDED - Flutter로 앱 개발 입문하기SuJang Yang
 
Next Generation Memory Forensics
Next Generation Memory ForensicsNext Generation Memory Forensics
Next Generation Memory ForensicsAndrew Case
 

Semelhante a Avoid loss of hair while coding Unity3D plugins for mobile (20)

Python Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIPython Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CI
 
Cross platform mobile apps using .NET
Cross platform mobile apps using .NETCross platform mobile apps using .NET
Cross platform mobile apps using .NET
 
NSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine Security
NSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine SecurityNSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine Security
NSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine Security
 
Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)
 
How to Build & Use OpenCL on OpenCV & Android NDK
How to Build & Use OpenCL on OpenCV & Android NDKHow to Build & Use OpenCL on OpenCV & Android NDK
How to Build & Use OpenCL on OpenCV & Android NDK
 
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
 
Appium Overview - by Daniel Puterman
Appium Overview - by Daniel PutermanAppium Overview - by Daniel Puterman
Appium Overview - by Daniel Puterman
 
EuroPython 2014 - How we switched our 800+ projects from Apache to uWSGI
EuroPython 2014 - How we switched our 800+ projects from Apache to uWSGIEuroPython 2014 - How we switched our 800+ projects from Apache to uWSGI
EuroPython 2014 - How we switched our 800+ projects from Apache to uWSGI
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile Devices
 
Porting your favourite cmdline tool to Android
Porting your favourite cmdline tool to AndroidPorting your favourite cmdline tool to Android
Porting your favourite cmdline tool to Android
 
Rapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
Rapid Prototyping Chatter with a PHP/Hack Canvas App on HerokuRapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
Rapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
 
Setting Apple's UI Automation Free with Appium
Setting Apple's UI Automation Free with AppiumSetting Apple's UI Automation Free with Appium
Setting Apple's UI Automation Free with Appium
 
Custom Buildpacks and Data Services
Custom Buildpacks and Data ServicesCustom Buildpacks and Data Services
Custom Buildpacks and Data Services
 
Create a-strong-two-factors-authentication-device-for-less-than-chf-100
Create a-strong-two-factors-authentication-device-for-less-than-chf-100Create a-strong-two-factors-authentication-device-for-less-than-chf-100
Create a-strong-two-factors-authentication-device-for-less-than-chf-100
 
Native Javascript apps with Phonegap - De Keijzer
Native Javascript apps with Phonegap - De KeijzerNative Javascript apps with Phonegap - De Keijzer
Native Javascript apps with Phonegap - De Keijzer
 
Native Javascript apps with PhoneGap 11-04-2014 Codemotion Rome
Native Javascript apps with PhoneGap 11-04-2014 Codemotion RomeNative Javascript apps with PhoneGap 11-04-2014 Codemotion Rome
Native Javascript apps with PhoneGap 11-04-2014 Codemotion Rome
 
Appenginejs (old presentation)
Appenginejs (old presentation)Appenginejs (old presentation)
Appenginejs (old presentation)
 
Flutter Forward EXTENDED - Flutter로 앱 개발 입문하기
Flutter Forward EXTENDED -  Flutter로 앱 개발 입문하기Flutter Forward EXTENDED -  Flutter로 앱 개발 입문하기
Flutter Forward EXTENDED - Flutter로 앱 개발 입문하기
 
Next Generation Memory Forensics
Next Generation Memory ForensicsNext Generation Memory Forensics
Next Generation Memory Forensics
 
Hexagonal architecture
Hexagonal architectureHexagonal architecture
Hexagonal architecture
 

Mais de Codemotion

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Codemotion
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyCodemotion
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaCodemotion
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserCodemotion
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 - Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Codemotion
 

Mais de Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Último

Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 

Último (20)

Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 

Avoid loss of hair while coding Unity3D plugins for mobile

  • 1. Valerio “Lotti” Riva – Interactive Project valerio.riva@gmail.com @ValerioRiva http://it.linkedin.com/in/valerioriva/ Avoid loss of hair while coding Unity3D plugins for mobile ROME 24 June 2014 – Valerio Riva Codemotion Tech Meetup #4 – Roma Summer Edition
  • 2. Nice to meet you! • Web / Game developer • Recent works @ Interactive Project • World Cup Juggler • OverVolt: crazy slot cars ROME 24 June 2014 – Valerio Riva 2
  • 3. Why develop a Unity3D mobile plugin? • Access to device native features • Implement third-party SDK (analytics, advertising, in-app purchases, game services, etc.) • Save/Earn money • Personal growth ROME 24 June 2014 – Valerio Riva 3
  • 4. Extending Unity 4.x • Unity supports C/C++ libraries. “extern”-alized functions/methods can be called from C# • All plugins must be placed inside “Assets/Plugins” folder • Platform-dependent plugins must be placed inside specific folders (x86, x86_64, Android, iOS, WP8, Metro, etc.) • Available only on Unity3D Pro/Mobile ROME 24 June 2014 – Valerio Riva 4
  • 5. Extending Unity (iOS) • Call externalized Object-C methods • Must wraps third-party SDK if their methods are not externalized • Gameobjects can receive messages from native code • Receiver methods declared on GO’s components must have only 1 string parameter as signature ROME 24 June 2014 – Valerio Riva 5
  • 6. Extending Unity (Android) • Use JNI (Java Native Interface), Unity provides Helper classes • Call native methods directly from Unity • Gameobjects can receive messages from native code • Receiver methods declared on GO’s components must have only 1 string parameter as signature • On specific cases, Unity Player activity must be extended • Android Manifest editing is often required ROME 24 June 2014 – Valerio Riva 6
  • 7. Extending Unity (WP8) • Access native code directly from Unity • Use of callbacks to return data from native code • Unity’s Mono (v2.6) doesn’t support .NET >= 4.0 • Artefacts are needed to use .NET >= 4.0 libaries • “Always” needs a fake and a real plugin – Unity will overwrite fake one with the real one automatically • In specific cases, write a plugin is a monkey job ROME 24 June 2014 – Valerio Riva 7
  • 8. Extending Unity (remarks) • Scripting define symbols are your friends • Native calls are CPU intensive • Provide fake results for in-editor usage • Every native UI call must run inside native UI thread • Every callback must run inside Unity thread (WP8) • Save time by testing plugin on a native app • Remember to include Unity library if needed • classes.jar • UnityEngine.dll ROME 24 June 2014 – Valerio Riva 8
  • 9. Case study: Flurry plugin • Wrap Flurry SDK to made it accessible from Unity • Flurry SDK is simple to use, just call static methods (Advertising, In-App Purchase, …, are more complex plugin) • We have to code wrappers for each platform • Place platforms SKDs on the right directories • FlurryAnalytics-4.0.0.jar -> Plugins/Android/ • libFlurry_5.0.0.a -> Plugins/iOS/ • FlurryWP8SDK.dll -> Plugins/WP8/ • FlurryWP8SDK.dll -> Plugins/ (the WP8 fake one) ROME 24 June 2014 – Valerio Riva 9
  • 10. Flurry plugin (iOS) • Flurry SDK is not “extern”-alized • Dictionary<string, string> must be translated somewhat to NSMutableDictionary • Each KeyValuePair<string,string> are concatenated to form a single string ROME 24 June 2014 – Valerio Riva 10 //FlurryiOS.h - created by PRADA Hsiung on 13/3/8. extern "C" { void FlurryiOS_startSession(unsigned char* apiKey); void FlurryiOS_setEventLoggingEnabled(BOOL bEnabled); void FlurryiOS_logEventWithParameters(unsigned char* eventId,unsigned char *parameters); }
  • 11. Flurry plugin (iOS) // FlurryiOS.m - created by Faizan Naqvi on 1/10/13. #import <stdio.h> #include "Flurry.h" //Flurry SDK headers void FlurryiOS_startSession(const char* apiKey) { NSString *str = [NSString stringWithUTF8String:apiKey]; [Flurry startSession:str]; } void FlurryiOS_setEventLoggingEnabled(BOOL bEnabled){ [Flurry setEventLoggingEnabled:bEnabled]; } ROME 24 June 2014 – Valerio Riva 11
  • 12. Flurry plugin (iOS) void FlurryiOS_logEventWithParameters(const char* eventId,const char *parameters) { NSString *params = [NSString stringWithUTF8String:parameters]; NSArray *arr = [params componentsSeparatedByString: @"n"]; NSMutableDictionary *pdict = [[[NSMutableDictionary alloc] init] autorelease]; for(int i=0;i < [arr count]; i++) { NSString *str1 = [arr objectAtIndex:i]; NSRange range = [str1 rangeOfString:@"="]; if (range.location!=NSNotFound) { NSString *key = [str1 substringToIndex:range.location]; NSString *val = [str1 substringFromIndex:range.location+1]; //NSLog(@"kv %@=%@n",key,val); [pdict setObject:val forKey:key]; } } if([pdict count]>0) { [Flurry logEvent:[NSString stringWithUTF8String:eventId] withParameters:pdict timed:false]; } else FlurryiOS_logEvent(eventId); } ROME 24 June 2014 – Valerio Riva 12
  • 13. Flurry plugin (iOS) Meanwhile on Unity side… #region FlurryiOS_Imports [DllImport("__Internal", CharSet = CharSet.Ansi)] private static extern void FlurryiOS_startSession([In, MarshalAs(UnmanagedType.LPStr)]string apiKey); [DllImport("__Internal")] private static extern void FlurryiOS_setEventLoggingEnabled(bool bEnabled); [DllImport("__Internal", CharSet = CharSet.Ansi)] private static extern void FlurryiOS_logEventWithParameters([In, MarshalAs(UnmanagedType.LPStr)]string evendId, [In, MarshalAs(UnmanagedType.LPStr)]string parameters); #endregion ROME 24 June 2014 – Valerio Riva 13
  • 14. Flurry plugin (WP8) • Flurry SDK is compiled with .NET 4.5, import it and Unity will go mad! • We need the “fake & real” library approach, but… • Using Flurry SDK doesn’t involve use of complex logic or complex user defined classes… • … we can use the downloaded FlurryWP8SDK.dll as “real” • and code only the fake dll! Yes, this is the particular case where you can bring in monkeys! ROME 24 June 2014 – Valerio Riva 14
  • 15. Flurry plugin (WP8) using FlurryWP8SDK.Models; using System; using System.Collections.Generic; namespace FlurryWP8SDK.Models { public enum Gender { Unknown = -1, Female = 0, Male = 1 } public class Parameter { public Parameter(string name, string value) { Name = name; Value = value; } public string Name { get; set; } public string Value { get; set; } } } namespace FlurryWP8SDK { public sealed class Api { private static Api instance = null; public static Api Current { get { return instance; } } public void DummyInitiator() {} public static void EndSession() {} public static void EndTimedEvent(string eventName) {} public static void EndTimedEvent(string eventName, List<Parameter> parameters) {} public static void LogEvent(string eventName) {} public static void LogEvent(string eventName, List<Parameter> parameters, bool timed) {} public static void SetAge(int age) {} public static void SetGender(Gender gender) {} public static void SetLocation(double latitude, double longitude, float accuracy) {} public static void SetSessionContinueSeconds(int seconds) {} public static void StartSession(string apiKey) {} } } ROME 24 June 2014 – Valerio Riva 15 That was easy, now give me peanuts!
  • 16. Flurry plugin (Android) • As said before, Flurry doesn’t involve complex logic… • … so we save time and wrote plugin directly in Unity using JNI Helper classes ROME 24 June 2014 – Valerio Riva 16 public Flurry StartSession(string apiKey) { #if !UNITY_EDITOR && UNITY_WP8 Api.StartSession(apiKey); #elif !UNITY_EDITOR && UNITY_ANDROID using(AndroidJavaClass cls_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using(AndroidJavaObject obj_Activity = cls_UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) using(AndroidJavaClass cls_FlurryAgent = new AndroidJavaClass("com.flurry.android.FlurryAgent")) { cls_FlurryAgent.CallStatic("onStartSession", obj_Activity, apiKey); } #elif !UNITY_EDITOR && UNITY_IPHONE FlurryiOS_startSession(apiKey); #endif return this; }
  • 17. Flurry plugin (Android) ROME 24 June 2014 – Valerio Riva 17 public Flurry LogEvent(string eventId, Dictionary<string,string> parameters, bool timed) { #if !UNITY_EDITOR && UNITY_WP8 List<Parameter> p = new List<Parameter>(); foreach(KeyValuePair<string,string> i in parameters) { p.Add(new Parameter(i.Key,i.Value)); } Api.LogEvent(eventId, p, timed); #elif !UNITY_EDITOR && UNITY_ANDROID using(AndroidJavaObject obj_HashMap = new AndroidJavaObject("java.util.HashMap")) { // Call 'put' via the JNI instead of using helper classes to avoid: "JNI: Init'd AndroidJavaObject with null ptr!" IntPtr method_Put = AndroidJNIHelper.GetMethodID(obj_HashMap.GetRawClass(), "put“, "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); object[] args = new object[2]; foreach(KeyValuePair<string, string> kvp in parameters) { using(AndroidJavaObject k = new AndroidJavaObject("java.lang.String", kvp.Key)) using(AndroidJavaObject v = new AndroidJavaObject("java.lang.String", kvp.Value)) { args[0] = k; args[1] = v; AndroidJNI.CallObjectMethod(obj_HashMap.GetRawObject(), method_Put, AndroidJNIHelper.CreateJNIArgArray(args)); } } cls_FlurryAgent.CallStatic("logEvent", eventId, obj_HashMap, timed); } #elif !UNITY_EDITOR && UNITY_IPHONE FlurryiOS_logEventWithParametersTimed(eventId, dictionaryToText(parameters)); #endif return this; }
  • 18. and for more complex plugins…? • Do most of logic on native side to minimize native calls from Unity • Messages examples (Android) UnityPlayer.UnitySendMessage("gameObjectName", "methodName", "message"); • Use “Action<…>” delegates to pass callbacks on WP8, Unity supports Action with max 4 parameters as .NET 3.5 does • Structure plugin as a wrapper (mainly for third-party SDKs) • Hide user defined classes (e.g.: instantiate them with methods) so Unity can’t see them • Wrap API calls with ones that use just primitive or built-in data type and the convert them to user defined classes inside plugin! ROME 24 June 2014 – Valerio Riva 18
  • 19. Run on UI Thread • iOS dispatch_async(dispatch_get_main_queue(), ^{ // Your code to run on the main queue/thread }); [[NSOperationQueue mainQueue] addOperationWithBlock:^{ // Your code to run on the main queue/thread }]; • Android UnityPlayer.currentActivity.runOnUiThread(new Runnable() { public void run() { //your code to run on the UI thread } }); ROME 24 June 2014 – Valerio Riva 19
  • 20. Run on UI Thread (WP8) • MainPage.xaml.cs public partial class MainPage : PhoneApplicationPage { public void InvokeOnAppThread ( Action callback ) { UnityApp.BeginInvoke ( () => { callback (); } ); } public void InvokeOnUIThread ( Action callback ) { Dispatcher.BeginInvoke ( () => { callback (); } ); } private void Unity_Loaded() { … MyDispatcher.InvokeOnAppThread = InvokeOnAppThread; MyDispatcher.InvokeOnUIThread = InvokeOnUIThread; … } } • MyPlugin.cs MyDispatcher.InvokeOnAppThread(() => { //your Unity callbacks execution must be placed here }); MyDispatcher.InvokeOnUIThread(() => { //your code to run on UI Thread }); ROME 24 June 2014 – Valerio Riva 20
  • 21. Resources and examples Resources • http://docs.unity3d.com/Manual/Plugins.html • http://docs.unity3d.com/Manual/wp8-plugins.html • http://docs.unity3d.com/Manual/PluginsForAndroid.html • http://docs.unity3d.com/Manual/PluginsForIOS.html Examples • https://github.com/playgameservices/play-games-plugin-for-unity • https://github.com/googleads/googleads-mobile- plugins/tree/master/unity • https://github.com/guillermocalvo/admob-unity-plugin • https://github.com/mikito/unity-admob-plugin • https://github.com/bearprada/flurry-unity-plugin • https://github.com/mikito/unity-flurry-plugin • https://github.com/faizann/unity3d_flurry ROME 24 June 2014 – Valerio Riva 21
  • 22. Thank you! ROME 24 June 2014 – Valerio Riva 22 Question Time No animals were harmed in the making of this talk valerio.riva@gmail.com @ValerioRiva http://it.linkedin.com/in/valerioriva/