I started working on a project that was built using OneSignal v1.15.2.
On Android everything works fine.
On iOS instead, I tried to follow this: https://documentation.onesignal.com/v3.0/docs/unity-sdk-setup (points [5.1 - 5.7]: they just add UserNotifications.framework)
Now, if I launch my application it crashes and the message is: "dyld: image not found".
If I remove UserNotifications.framework the all game runs ok but notifications.
Is the current version of OneSignal so different from the past? Is there another setup process guide that I should follow?
I'm using Unity 5.3.1p4 and XCode 8.2.1 (I was using XCode 8.3.1 and notifications worked well, but this newer version have some documented incompatibility with Unity 5.3.1p4).
Can anyone help me?
Thank you.
Best regard,
Andrea.
For what it's worth I'm using Unity 5.6.0 and Xcode 8.3.2 with the SDK Unity5OneSignalSDK.unitypackage and points 5.1 through 5.7 where sufficient to get push notifications working.
I am also automating the background modes to check "remote-notifications" using the following post processor ... I can't find a way to automate the link with UserNotifications.framework yet tho ... let me know if anybody has ideas on how to do that.
// ---------------------------------------------------------------------------------------------------------------------
public static class XCodePostProcess
{
// -----------------------------------------------------------------------------------------------------------------
[PostProcessBuild(100)]
public static void OnPostprocessBuild( BuildTarget target, string pathToBuildProject )
{
if (target == BuildTarget.iOS)
{
UpdateInfoPlist( pathToBuildProject );
}
}
// -----------------------------------------------------------------------------------------------------------------
private static void UpdateInfoPlist( string path )
{
// load plist
string plistPath = Path.Combine( path, "Info.plist" );
PlistDocument plist = new PlistDocument();
plist.ReadFromString( File.ReadAllText( plistPath ) );
//Get Root
PlistElementDict rootDict = plist.root;
//Add Necessary Things
PlistElementArray LSApplicationQueriesSchemes = rootDict.CreateArray( "LSApplicationQueriesSchemes" );
LSApplicationQueriesSchemes.AddString( "itms-beta" ); // test flight
// localizations
PlistElementArray CFBundleLocalizations = rootDict.CreateArray( "CFBundleLocalizations" );
CFBundleLocalizations.AddString( "en" ); // english
CFBundleLocalizations.AddString( "de" ); // german
CFBundleLocalizations.AddString( "fr" ); // french
CFBundleLocalizations.AddString( "es" ); // spanish
// for OneSigna remote notifications
PlistElementArray UIBackgroundModes = rootDict.CreateArray( "UIBackgroundModes" );
UIBackgroundModes.AddString( "remote-notification" );
//WriteFile
File.WriteAllText (plistPath, plist.WriteToString ());
}
}
Related
We are using the Facebook Unity SDK 15.1.0 in Unity 2019.4.40f1. This SDK has some serious bugs. One of them is that it won't add the required frameworks to the Unity-iPhone target. The project will build, but immediately crash on startup.
The frameworks are there, but in a Pod:
I can add them manually in the General => Frameworks, Libraries, and Embedded Content section of the target:
Everything works fine then.
However, doing this after every build is quite tedious, so I would like to automate this task via a post build script. I am scratching my head about this, since I cannot find good samples online that actually work.
So my question is: How do you add a .xcframework buried in Facebook SDK's pods so it correctly shows up in the target?
Here is how i would do it. This may not be 100% correct but good enough to modify it to make it work for you. Basically you need to use PBXProject.AddFrameworkToProject to add frameworks.
#if UNITY_IOS
[PostProcessBuild(1)]
public static void ChangeXcodePlist(BuildTarget buildTarget, string pathToBuiltProject) {
if (buildTarget == BuildTarget.iOS) {
// get pbx project path
var projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
if (File.Exists(projPath))
{
var proj = new PBXProject();
proj.ReadFromString(File.ReadAllText(projPath));
string mainTargetGuid = null, testTargetGuid = null, frameworkTargetGuid = null;
#if UNITY_2019_4_OR_NEWER // APIs are different for getting main unity targets changes based on versions
mainTargetGuid = proj.GetUnityMainTargetGuid();
frameworkTargetGuid = proj.GetUnityFrameworkTargetGuid();
#else
mainTargetGuid =
proj.TargetGuidByName(PBXProject.GetUnityTargetName());
testTargetGuid =
proj.TargetGuidByName(PBXProject.GetUnityTestTargetName());
frameworkTargetGuid = proj.TargetGuidByName("UnityFramework");
#endif
// add your frameworks here
if (!String.IsNullOrEmpty(mainTargetGuid))
{
Debug.Log("Adding targets to mainTargetGuid")
proj.AddFrameworkToProject(mainTargetGuid, "FBSDKCoreKit.xcframework", false);
proj.AddFrameworkToProject(mainTargetGuid, "FBSDKGamingServicesKit.xcframework", false);
}
// add to test target aswell if exists
if (!String.IsNullOrEmpty(testTargetGuid))
{
Debug.Log("Adding targets to testTargetGuid")
proj.AddFrameworkToProject(mainTargetGuid, "FBSDKCoreKit.xcframework", false);
proj.AddFrameworkToProject(mainTargetGuid, "FBSDKGamingServicesKit.xcframework", false);
}
if (!String.IsNullOrEmpty(frameworkTargetGuid))
{
Debug.Log("Adding targets to frameworkTargetGuid")
proj.AddFrameworkToProject(mainTargetGuid, "FBSDKCoreKit.xcframework", false);
proj.AddFrameworkToProject(mainTargetGuid, "FBSDKGamingServicesKit.xcframework", false);
}
proj.WriteToFile(projPath);
}
}
}
#endif
You can also use PBXProject.ContainsFramework before you include the frameworks.
The code in the previous answer is not working. Freimworks are not added like that.
Correct code for adding facebook's frameworks (working):
[PostProcessBuild(1000)]
public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject) {
if (buildTarget != BuildTarget.iOS) return;
string projectPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
PBXProject project = new PBXProject();
project.ReadFromFile(projectPath);
string mainTargetGuid = project.GetUnityMainTargetGuid();
List<string> frameworks = new List<string> {
"FBSDKCoreKit",
"FBSDKGamingServicesKit"
};
foreach (string framework in frameworks) {
string frameworkName = framework + ".xcframework";
var src = Path.Combine("Pods", framework, "XCFrameworks", frameworkName);
var frameworkPath = project.AddFile(src, src);
project.AddFileToBuild(mainTargetGuid, frameworkPath);
project.AddFileToEmbedFrameworks(mainTargetGuid, frameworkPath);
}
// Write.
project.WriteToFile(projectPath);
}
Build environment:
Macbook M1
vscode(1.69.0) as well as vs2022 (17.3)
Steps to reproduce:
create new Maui app
add nuget package "Microsoft.Extensions.Http" Version="6.0.0" to project
Modify MauiProgram.cs:
builder.Services.AddHttpClient<EndPointAHttpClient>(client =>
{
var EndPointA = "https://www.montemagno.com/";
client.BaseAddress = new Uri(EndPointA);
});
public class EndPointAHttpClient
{
public EndPointAHttpClient(HttpClient client)
{
Client = client;
}
public HttpClient Client { get; }
}
Publish:
dotnet publish <project.csproj> -f:net6.0-ios -c:Release /p:ServerAddress=<xxx.xxx.xxx.xxx> /p:ServerUser=user /p:TcpPort=58181 /p:ServerPassword=pwd -p:AotAssemblies=false
Install on iphone using Transporter/TestFlight
CRASHES WHEN OPENING THE APP
Please let me know:
1. Is there any demo code that works
2. Kindly provide advise on how I can use HttpClient in a .net Maui app
Use the code found here. https://github.com/dotnet/maui-samples/tree/main/6.0/WebServices/TodoREST/TodoREST/Services
Grab the RestService, IRestService, HttpsClientHandlerService and IHttpsClientHandlerService.
Get the Contstants file as well.
https://github.com/dotnet/maui-samples/blob/main/6.0/WebServices/TodoREST/TodoREST/Constants.cs
Makes sure you add your Url to the HttpsClientHandlerService like so. I was getting a System.Net.WebException: Error: TrustFailure. The only way I was able to catch what was happening was using Sentry.io. I guessed that this might be the problem.
public bool IsSafeUrl(NSUrlSessionHandler sender, string url, Security.SecTrust trust)
{
if (url.StartsWith("https://localhost") || url.StartsWith("https://yourservice.azurewebsites.net"))
return true;
return false;
}
Then change this line.
var handler = new NSUrlSessionHandler
{
TrustOverrideForUrl = IsSafeUrl
};
I have not found any official Apple document that discusses correctly implementing push notification simultaneously for old iOS versions, as well as iOS 10. And the independent tutorials I have seen, likewise cover a single iOS version.
I see this official document for iOS 10:
Local and Remote Notifications Overview But it doesn't comment on supporting earlier iOS versions.
And a tutorial for iOS 9:
Push Notifications Tutorial - Ray Wenderlich
And I see various stackoverflow threads about changes people had to make to get their old solutions to work on newer versions:
Push notifications are not working in iOS 9
Which does show code for handling 6 - 9.
didReceiveRemoteNotification not called , iOS 10
BUT what I don't see, is what is correct to do, starting today (with iOS 10), but also supporting older devices. ** UPDATE ** App Store says only 6% of devices downloading apps are older than ios 9, so if it is easier to just support 9 + 10, i'll just do that.
(I tried starting with an iOS 10 example, but it immediately crashed on iOS 9.3 emulated device, though it works fine in iOS 10. So I conclude that I should be starting with information about correctly setting up for the different versions. I could post that code, but I think that leads this thread in the wrong direction. I would rather start with what "should" work on multiple versions of iOS, including 10.)
If I don't find some solution, I'll start combining code from different stackoverflow code snippets ... but seriously? I must be missing something, as presumably every iOS developer has this issue.
Conversely, I could start with an older example, and then follow the changes to get that to work with iOS 10 - but will that take full advantage of iOS 10?
NOTE: I'm programming in Xamarin C#, but Objective-C or Swift answer is just as useful.
This is Xamarin C# code (different syntax and capitalization than Objective-C, but I think it is translatable line-by-line to Objective-C).
Tested on both iOS 9.3 and iOS 10.2.
To initialize "local" and "remote" notifications:
// "UIApplicationDelegate" is for "local" notifications,
// "IUNUserNotificationCenterDelegate, IMessagingDelegate" for "remote" notifications.
public class AppDelegate : UIApplicationDelegate,
IUNUserNotificationCenterDelegate, IMessagingDelegate
{
...
public override bool FinishedLaunching( UIApplication application, NSDictionary launchOptions )
{
...
RegisterForOurRemoteNotifications( this );
RegisterForOurLocalNotifications();
...
}
...
// --- Comment out if not using Google FCM. ---
public override void RegisteredForRemoteNotifications( UIApplication application, NSData deviceToken )
{
//base.RegisteredForRemoteNotifications( application, deviceToken );
Firebase.InstanceID.InstanceId.SharedInstance.SetApnsToken( deviceToken,
Firebase.InstanceID.ApnsTokenType.Sandbox );
}
...
// ----- "static"; Could be in another class. -----
// These flags are for our convenience, so we know initialization was done.
static bool IsRegisteredForNotifications;
static bool IsRegisteredForRemoteNotifications;
// Optional - true when we are using Google "Firebase Cloud Messaging".
static bool HasFCM;
public static void RegisterForOurRemoteNotifications( AppDelegate del )
{
// Google "Firebase Cloud Messaging" (FCM) Monitor token generation
// (Uncomment, if you are using FCM for notifications.)
//InstanceId.Notifications.ObserveTokenRefresh( TokenRefreshNotification );
if (UIDevice.CurrentDevice.CheckSystemVersion( 10, 0 )) {
// iOS 10 or later
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization( authOptions, ( granted, error ) => {
Console.WriteLine( granted );
} );
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = del;
// For iOS 10 data message (sent via Google FCM).
// (Uncomment, if you are using FCM for notifications.)
// TBD: If NOT using FCM, you may need some other lines of code here.
//Messaging.SharedInstance.RemoteMessageDelegate = del;
} else {
// iOS 9 or before
var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings.GetSettingsForTypes( allNotificationTypes, null );
UIApplication.SharedApplication.RegisterUserNotificationSettings( settings );
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
IsRegisteredForRemoteNotifications = true;
// Uncomment if using Google "Firebase Cloud Messaging" (FCM).
//TokenRefreshNotification( null, null );
//if (UIDevice.CurrentDevice.CheckSystemVersion( 9, 0 )) // Needed to call this twice on iOS 9 for some reason.
// TokenRefreshNotification( null, null );
UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval( UIApplication.BackgroundFetchIntervalMinimum );
}
public static void RegisterForOurLocalNotifications()
{
// --- Our app's notification actions. ---
UNNotificationAction followAction = UNNotificationAction.FromIdentifier( "follow", PS.LocalizedString( "Follow" ), UNNotificationActionOptions.None );
UNNotificationAction likeAction = UNNotificationAction.FromIdentifier( "like", PS.LocalizedString( "Like" ), UNNotificationActionOptions.None );
// ...
// --- Our app's notification categories ---
UNNotificationCategory followCategory = UNNotificationCategory.FromIdentifier( "followCategory", new UNNotificationAction[] { followAction, likeAction },
new string[] { }, UNNotificationCategoryOptions.None );
// ...
// --- All of the app's categories from above ---
var categories = new UNNotificationCategory[] { followCategory /*, ...*/ };
// --- Same for all apps ---
UIUserNotificationSettings settings = UIUserNotificationSettings.GetSettingsForTypes(
UIUserNotificationType.Alert |
UIUserNotificationType.Badge |
UIUserNotificationType.Sound
, new NSSet( categories ) );
UIApplication.SharedApplication.RegisterUserNotificationSettings( settings );
if (UIDevice.CurrentDevice.CheckSystemVersion( 10, 0 )) {
UNUserNotificationCenter.Current.SetNotificationCategories( new NSSet<UNNotificationCategory>( categories ) );
UNUserNotificationCenter.Current.RequestAuthorization( UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound | UNAuthorizationOptions.Badge,
( result, err ) => {
Console.WriteLine( result.ToString() );
} );
}
IsRegisteredForNotifications = true;
}
}
// -------------------------------------------------------
// --- These are for Google "Firebase Cloud Messaging" ---
// (Comment out if not using FCM.)
public static string Token;
static void TokenRefreshNotification( object sender, NSNotificationEventArgs e )
{
// This method will be fired every time a new token is generated, including the first
// time. So if you need to retrieve the token as soon as it is available this is where that
// should be done.
//var refreshedToken = InstanceId.SharedInstance.Token;
ConnectToFCM( UIApplication.SharedApplication.KeyWindow.RootViewController );
// TODO: If necessary send token to application server.
}
public static void ConnectToFCM( UIViewController fromViewController )
{
Messaging.SharedInstance.Connect( error => {
if (error != null) {
Helper.logD( "Unable to connect to FCM", error.LocalizedDescription );
} else {
//var options = new NSDictionary();
//options.SetValueForKey( DeviceToken, Constants.RegisterAPNSOption );
//options.SetValueForKey( new NSNumber( true ), Constants.APNSServerTypeSandboxOption );
//InstanceId.SharedInstance.GetToken("", InstanceId.ScopeFirebaseMessaging
Token = InstanceId.SharedInstance.Token;
Console.WriteLine( $"Token: {InstanceId.SharedInstance.Token}" );
HasFCM = true;
}
} );
}
// ------------------ End Google FCM ---------------------
// -------------------------------------------------------
}
The above code initializes your app so that it can receive notifications.
IMPORTANT: You also need to set appropriate permissions on your app; see Apple docs, or links mentioned in the question. And you need this file:
Entitlements.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
<string> above must contain either "development" or "production". (I don't know the significance of our app still saying "development" here; I haven't examined what is built to see if it gets automatically changed to "production" by Xcode before submission to Apple. According to https://stackoverflow.com/a/40857877/199364 it does.)
Then you need code to send [e.g. your app tells your server to notify your friends' devices of what you are doing now] and receive a local or remote notification. That code, in our app, is combined with our specific notification actions and categories; I do not have time to extract a concise version to post here. Please see Apple docs, or links mentioned in the original question, for full details.
Here are the essential methods (Add to class AppDelegate above) to receive notifications:
public override void ReceivedLocalNotification( UIApplication application, UILocalNotification notification )
{
...
}
public override void DidReceiveRemoteNotification( UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler )
{
...
}
[Export( "userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:" )]
public void DidReceiveNotificationResponse( UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler )
{
...
}
Other methods that you may want/need to override or implement (also see the interfaces declared on class AppDelegate above); some of these might be specific to FCM:
ApplicationReceivedRemoteMessage
ReceivedRemoteNotification
WillPresentNotification
PerformFetch (for background notifications)
HandleAction
I have done a lot of searching online and I'm not sure what I'm doing wrong. The idea is that I want to launch my iOS app with the following location in a simulator. This works fine when I manually go to debug>location>custom location and set the longitude and latitude....however I need to do it programatically so that my app launches /picks up this location when I click enable locations. Here is my code
public class SampleTest extends SampleBaseTest {
private IOSDriver driver;
private String sessionId;
static UserData sampleUser = null;
#Test(priority = 0)
public void setUp() throws MalformedURLException {
DesiredCapabilities caps = DesiredCapabilities.iphone();
caps.setCapability("appiumVersion", "1.4.16");
caps.setCapability("deviceName","iPhone 6");
caps.setCapability("deviceOrientation", "portrait");
caps.setCapability("platformVersion","9.1");
caps.setCapability("platformName", "iOS");
caps.setCapability("browserName", "");
caps.setCapability("app","sauce-storage:sampleAppe.zip");
URL sauceUrl = new URL("http://" + "sauceUserName" + ":"+ "sauceUserKey" + "#ondemand.saucelabs.com:80/wd/hub");
driver = new IOSDriver(sauceUrl, caps);
Location location = new Location(-8.78319, -114.509, 0.0);
driver.setLocation(location);
sessionId = driver.getSessionId().toString();
#Test(priority = 1)
public void navigateToPayAhead()
throws Exception {
try{
// test logic here
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
Unfortunately, there is a current issue with setting a location on the Sauce iOS simulators. From a support ticket on a similar issue, I was told that it is a known issue, and that it will be addressed (at some point).
I can verify that setting a location does work when using the Android emulators via Sauce Labs.
So, I guess the good news is that you aren't doing anything wrong!
Try adding
caps.setCapability("locationServicesEnabled", true);
caps.setCapability("locationServicesAuthorized", true);
caps.setCapability("bundleId", "YOUR_BUNDLE_ID_HERE");
To get your bundle id, see How to obtain Bundle ID for an IOS App when I have a '.ipa' file for the app installed on my iPAD
i just finished creating an iOS and Android application with Air ( SDK 18 )
I get an Error #0 ( sometimes - inconsistable ) when trying to save a preferences file.
The code is quite straightforward:
private static var _file:File=File.applicationStorageDirectory.resolvePath(CONFIGFILE);
private static function saveFile():void{
var fileStream:FileStream = new FileStream();
if(File.applicationStorageDirectory.spaceAvailable>1024){
fileStream.open(_file, FileMode.WRITE);
fileStream.writeUTFBytes(Base64.encrypt(JSON.stringify(ob),Strings.HASHSALT));
fileStream.close();
}else{
showLowSpaceAlert()
}
}
On Android eveything works fine and on iOS there are no issues 50% of the time ...
Anyone know this bug? Thanks!
Do not try to create a File object with a static variable, static objects are created during the app init time and timing issues are likely to appear. Your problem is due to your code logic.
The correct way is:
private static var _file:File;
then:
private static function saveFile():void
{
if(!_file)
{
_file = File.applicationStorageDirectory.resolvePath(CONFIGFILE);
}
//etc ...
}
I have only ever gotten this error when a device it out of space. You might try these calls...
trace( File.applicationStorageDirectory.spaceAvailable );
trace( File.cacheDirectory.spaceAvailable );
...to get how many bytes of space are available to you. For example...
var data:String = Base64.encrypt(JSON.stringify(ob),Strings.HASHSALT);
if ( data.length > File.cacheDirectory.spaceAvailable )
{
trace( "NOT ENOUGH SPACE" );
}
else
{
trace( "OK TO SAVE" );
}
The question have been asked on Adobe Forum and the OP tends to says that the issue is because the iOs device lakes of free space.
You should consider freeing a bit of memory on your device.