Xamarin.Android: How to handle deprecacy issue with TimePicker widget? - xamarin.android

I'm creating a simple App in which TimePickers are used to capture the hour and the minute. I use code to do this like the following:
end.AddHours(view.FindViewById<TimePicker>(Resource.Id.endPicker).Hour);
end.AddMinutes(view.FindViewById<TimePicker>(Resource.Id.endPicker).Minute);
The problem is with the Hourand the Minute properties, while end is a DateTime.
On KitKat API lvl 19, Visual Studio gives me the following error:
On MarshMallow API lvl 23, however, the App runs very well. So the problem must be that the Java getCurrentMinute/Hour methods were exchanged in later APIs for the getMinute/Hour methods as it is written here. Is there a way to use the earlier methods in earlier APIs and use the most recent methods on later ones? Can I code this into my Xamarin.Android App? In Native Android I would of course check the SDK version and use Java methods accordingly, but I don't know if I can force the underlying Java code to behave this way.
UPDATE
Following the suggestion of Janmejoy , I created an if statement to check the Android version in problematic cases like this one and used deprecated code:
if(((int)Android.OS.Build.VERSION.SdkInt) < 23)
{
start = new DateTime(1, 1, 1, (int)view.FindViewById<TimePicker>(Resource.Id.startPicker).CurrentHour,
(int)view.FindViewById<TimePicker>(Resource.Id.startPicker).CurrentMinute, 0);
end = new DateTime(1, 1, 1, (int)view.FindViewById<TimePicker>(Resource.Id.endPicker).CurrentHour,
(int)view.FindViewById<TimePicker>(Resource.Id.endPicker).CurrentMinute, 0);
}
This seemed to work, however, my App was extremely slow on the emulated KitKat device (it runs flawlessly on a 1 GB Marsh, but it appears to be buggy on an earlier device with 762 MB RAM). What is worse, the App now looks the same on both Marsh and KitKat exhibiting the same buggy behavior. I deleted the App from both devices, commented out the deprecated code and done a RebuildAll, but this strange behavior still persists. Has anyone seen any similar? What might be the problem?

In Native Android I would of course check the SDK version and use
Java methods accordingly,
Yes You are right ! You can try like this in Xamarin also
if (((int)Android.OS.Build.VERSION.SdkInt) >= 23){
//
}
else{//}
#see https://developer.xamarin.com/api/property/Android.OS.Build+VERSION.SdkInt/

Related

Using schedule() on an iOS project

I'm trying to use schedule(deadline:repeating:leeway:) on an iOS project. In a counterpart macOS project it works fine, but in the iOS project I get an error:
'schedule(deadline:repeating:leeway:)' is unavailable
Here is a part of the code:
var timeoutTimer : DispatchSourceTimer?
func startUpdateTimer(){
let delay : DispatchTime = .now() + .seconds(3)
if timeoutTimer == nil {
timeoutTimer = DispatchSource.makeTimerSource()
timeoutTimer!.schedule(deadline: delay, repeating: 0) // Error: 'schedule(deadline:repeating:leeway:)' is unavailable
...
Doc 1:
https://developer.apple.com/documentation/dispatch/dispatchsourcetimer/2920395-schedule
I would like to understand if I'm doing something wrong, could someone tell me if this code should work on iOS?
PS
Using scheduleRepeating(deadline:interval:leeway:) which is deprecated instead of schedule(deadline:repeating:leeway:) seems to work. At the moment unfortunately I do not have enough knowledge to understand how the two statements differ.
timeoutTimer!.scheduleRepeating(deadline: delay, interval: 0)
Doc 2: https://developer.apple.com/documentation/dispatch/dispatchsourcetimer/2016072-schedulerepeating
scheduleRepeating(deadline:interval:leeway:) was introduced in iOS 7/macOS 10.9 and has been deprecated in iOS 11/macOS 10.13.
Initially Apple offered scheduleRepeating and scheduleOneshot variants but this made no sense as if a timer is repeating or oneshot can be deducted solely by arguments passed to the function. Now they only offer schedule(deadline:repeating:leeway:), and if called with a non-zero value for repeating, the timer is repeating, otherwise it is oneshot.
However, please note that in fact GCD timers are not real objects, neither Swift objects nor Objective-C objects, in fact they are C structures represented as opaque pointers. If you create such a GCD object in C or Obj-C, the code is like this:
dispatch_source_t ds = dispatch_source_create(
DISPATCH_SOURCE_TYPE_TIMER, 0, 0, someQueue
);
dispatch_source_set_timer(ds, startTime, interval, leeway);
Making GCD Objects appear as Swift objects is actually some "magic" built into Xcode and the Swift SDK. schedule(deadline:repeating:leeway:) is only available if you use Xcode 9+ and Swift 4. If you use Xcode 8.x or if you use Swift 3 in Xcode 9+, then only the deprecated scheduleRepeating(deadline:interval:leeway:) is available.
Unlike with other API, that's not a question of the iOS/macOS SDK version you build for, as this magic is not provided by the iOS/macOS SDK, it depends on the Swift SDK version you build for and this version is independent of the target operating system, as the SDK is embedded into your app and thus shipped together with your app.
That's why you can use schedule(deadline:repeating:leeway:) in Swift 4 in Xcode 9+ and still deploy all the way down to iOS 7.0/macOS 10.9, since only for your Swift code the call has changed, internally it uses the same GCD API calls that the deprecated methods were using before, so the compiled code runs just fine even on these old OS versions.
To answer your question on how the statements differ: Well, they have different names and the arguments have different names, other than that the argument types are identically and they also work identically.

Script to search Xcode project for OS specific selectors

I've produced a project that runs fine on iOS 8 (there are no unit tests though). It's a rather large project, and I don't have time to test all the features on a different operating system. I however, want to determine whether it would run with the same stability on iOS 7.
Of course, there are plenty of reasons that it wouldn't aside from the fact of using iOS 8 specific methods, however I've had a google for a script or process that would have:
functionality to determine whether my Xcode project has iOS 8 specific methods, and if so, where.
For instance, this method has tripped me up before:
- (BOOL)containsString:(NSString *)aString NS_AVAILABLE(10_10, 8_0);
Is there anyway of pulling all the method declaration information, and the OS availability of it, and then using that to parse the current Xcode project to determine whether I'm using code that will only run on iOS 8?
Or is this an impossible ask?

Project is buggy after upgrading Xcode

I have an old app I maintaining. The app was first compiled on XCode 4.2. If I take the exact same project that works find and compile it on XCode 4.6 I'll get weird bugs such as ViewControllers not refreshing, Back doesn't work as it should etc'. If I'll take the same project and recompile it on xcode 4.2 on my other machine everything will work fine. Before I'm digging into the code, can someone give me an idea why something like this may happen? My main suspect is the Base SDK of each Xcode. Does that make sense?
I couldn't tell you if there will be a difference between 4.2 and 4.6, but historically the iOS frameworks on the device (and, to a lesser degree, the simulator) do adapt slightly depending on what version of the SDK an application was compiled against. You can't rule it out.
A classic (though now ancient) example is backgrounding. Apps built against older SDKs were quit when the Home button was pushed, rather than getting the newer behaviour. More recent (but subtle) examples have included several changes to table views and changes to device rotation.
You should not attempt to build with an older SDK using a newer compiler. Apple doesn't support that kind of configuration. You should always use the latest SDK. And you wouldn't want to pretend these problems don't exist, anyway: The bugs are real, they were just hidden before.
It's unlikely that you won't be able to fix those bugs in such a way that the older versions of iOS continue to function (though you may discover it opens a can of worms that you decide isn't worth fixing for older OSes).

Monodroid cleartask flag available?

I need to run an activity and remove all the other activities for my application to save memory. I have seen in the sdk that the flag FLAG_ACTIVITY_CLEAR_TASK does exactly this but I can't find it in the ActivityFlags enum in monodroid.
Is this possible to be done with monodroid?
ActivityFlags.ClearTask is available in Mono for Android. However, Android didn't introduce this flag until API version 11, so I'm guessing that you're targeting a previous version. In order to use this flag, you'll need to update the minimum version of Android you target to 3.1, which is configurable in the project's properties page.
Edit: This question has some other approaches you can take to do this on previous versions of Android.

"Bad system call: 12" crashes when using a static framework on iOS with IPA-deployment (not Xcode run)

I'm working with a static framework I've created (built with the help of Karl Stenerud's iOS-Universal-Framework toolchain), which I intend to distribute. A static framework's a bit more convenient than simply using a static lib + headers - I like the ability to just drop a framework in and begin using it immediately, instead of needing to do things like set up appropriate header search paths.
However, I'm seeing some downright bizarre behaviour. Several test/sample apps that I have built with the framework are crashing with either "Bad system call: 12" or "Job appears to have crashed: Illegal instruction: 4" when run on iOS devices to which the app has been deployed via an ipa.
The code itself is fine. The crash does not occur when a static library is used instead of a framework. It also doesn't crash if the app is deployed via the debugger in Xcode, even when the Release build configuration is used.
The crash only happens when deployed via an ipa, and when the library is linked as a static framework.
Interestingly, the corresponding crash log's stack trace entries leading up to the crash (which is EXC_CRASH or EXC_BAD_INSTRUCTION) cannot be symbolicated.
In one instance, I was able to track the crash down to the point where a static C function is called. By removing the "static" keyword on a whim, I was able to stop the crash happening.
Unfortunately, this doesn't appear to be the silver bullet - I'm also seeing a crash on a non-static C function call.
But in all cases, the crash occurs when a C function is being called.
So, my question is this: Has anyone else seen this before? Any theories? Is this likely to be an LLVM bug? Some magical compiler/linker flag I'm missing? Have Apple deliberately only half-supported static frameworks because there are issues? Do I just need to abandon my plan to distribute a framework, instead of a static library and assorted detritus?
Many thanks in advance,
Michael
The problem would appear to be related to static recursive functions!
Quoting Karl Stenerud, who figured it out:
It fails if you have a static recursive function:
#implementation Fibonacci
static int internalFibonacci(int value)
{
if(value <= 1)
{
return value;
}
return internalFibonacci(value - 1) + internalFibonacci(value - 2);
}
+ (int) fibonacci:(int) value
{
return internalFibonacci(value);
}
#end
If you call [Fibonacci fibonacci:] it will fail with "Bad system call: 12".
If you remove "static" from internalFibonacci(), it works perfectly.
I already came across similar issues. I develop iOS frameworks for a company and we provide those framework to clients who develop their own applications or framework above ours.
When we perform testing in our own, everything seems to work fine and applications just work perfectly. But as soon as applications/frameworks are built using different Xcode/Compiler version, there is no guarantee that everything will work just as expected.
The crashes that clients reported to us do always mention a bad code execution or bad arm instruction (the same as you got).
We searched a lot around the Apple developer forums but there few mentions to this issue, and Apple doesn't really seem to want to communicate about that.
From my experience, here are some clues that may perhaps help you:
Build your framework on Xcode 4.1, iOS SDK 4.3 and Apple LLVM 2.1
on OS X Lion, Xcode 4.3 you can build using LLVM GCC and make sure to disable THUMB support in your build settings.
You can try the last solution. I have made many tests with all possible compilers on OS X Lion, and so far, this configuration appears to be stable.
I haven't tested yet the new Xcode 4.3.2 and iOS SDK 5.1. I'll let you know as soon as I do it.
Regards,
Hichem

Resources