I have two ane file for video recorder. One is for android and another is for ios device. Both have different package name and methods.
Now, i import both Native Extension in single project. And detect ios and android device following way:
if(Capabilities.version.indexOf('IOS') > -1) //for ios device
And
if(Capabilities.version.indexOf('AND') > -1) //for android device
And create object for each class. Now when i run that it gives error for another ane class not found.
Like Suppose i check in ios then gives error for android ane file class, Event not found. same for android.
If you have an ANE that only supports Android it won't be available at all when run in Ios (same is true for Ios). If it has a default implementation its classes will be available but if it doesn't then its classes will just not exist in that scope and error will be thrown if you try to reference them. When using ANE that only offer one platform implementation those ANE have to be used only when compiling for that platform. The way you can switch between ANEs easily is by using CONFIG constants.
EDIT: Defining constants. Right Click project and choose "properties", in "Actionscript compiler" add as many config lines as you see fit, for example:
-define=CONFIG::ANDROID,false
-define=CONFIG::IOS,false
Now wrap all code (including import statements) referencing the Android ANE and the IOS ANE with:
CONFIG::ANDROID
{
//android code here
}
CONFIG::IOS
{
//ios code here
}
Now your 2 config variables are set to false so no code in between "CONFIG::ANDROID" or "CONFIG::IOS" will be compiled with your app. Now if in "actionscript compiler" you change:
-define=CONFIG::ANDROID,true
All code that is in between "CONFIG::ANDROID" will be compiled (you can use "CONFIG::ANDROID" anywhere in your code as many times as you want).
So before compiling set one config to true and make sure the other is set to false and the right code for the right platform will be compiled.
Capabilities.version will tell you: "Specifies the Flash Player or Adobe® AIR® platform and version information." and not the OS version you are running on.
See here http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/Capabilities.html#version
You need to use Capabilities.os instead
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/Capabilities.html#os
Related
I have some code that is written in Java and Kotlin for Android; the Java part can be translated into Kotlin using the Android Studio. Most of this code is business; that means, independent on any hardware or platform specifics; some Android specific classes (like "Bitmap") can be replaced by abstract or general self-defined classes.
As already known, Kotlin business code can be used in multiplatform applications for Android and iOS. Description here : https://kotlinlang.org/docs/multiplatform-mobile-integrate-in-existing-app.html .
Xamarin is used for multiplatform apps, too.
On the other hand, there is a way to include Kotlin code in Xamarin projects. For this purpose, the Xamarin.Kotlin.StdLib is used : https://libraries.io/nuget/Xamarin.Kotlin.StdLib .
My question: Is it possible to develop a Xamarin project (maybe with Xamarin Forms) that includes the Kotlin business code and will work in both Android and iOS environments?
Here are some instructions.
ANDROID STUDIO
Create a new Project: "File -> New -> New Module -> Kotlin
Multiplatform Shared Module".
Follow these instructions:
https://kotlinlang.org/docs/multiplatform-mobile-integrate-in-existing-app.html
until "Run your cross-platform application on Android".
For Android we're finished. Following steps are only for iOS.
We now assume that there is a module with the name "shared". If this module has another name, please replace it in the following instructions.
XCODE:
The following instructions are similar to that in https://kotlinlang.org/docs/multiplatform-mobile-integrate-in-existing-app.html#make-your-cross-platform-application-work-on-ios . The difference is that we don't want to build the app now, but a framework.
File New - Project.
Select the template for "Framework" and click "Next".
Choose a product name (for example, "KmmExample"). Language:
Objective C
Build Phases - New Run Script Phase:
cd "$SRCROOT/.."
chmod +x gradlew
./gradlew :shared:embedAndSignAppleFrameworkForXcode
Move the Run Script phase up so that it is located after the
"Dependencies" item.
On the Build Settings tab, switch to "All" build settings.
In the Search Paths paragraph, specify the Framework Search Path for both Debug and Release:
$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)
In the Linking paragraph:
Specify the "Mach-O Type" as "Static Library".
Specify the Other Linker Flags as
$(inherited) -framework shared
In the Architectures paragraph, "Architectures" may be unchanged or changed to "$(ARCHS_STANDARD_INCLUDING_64_BIT)".
Build the project.
If successful, there will be a folder structure inside "shared/build". There will be a subfolder "xcode-frameworks". In the "Debug" resp. "Release" directory, there will be subfolder(s) with the name(s) of the iOS device(s) or simulator(s). For example, "iphonesimulator15.5". It contains another subfolder: "shared.framework". In the "Headers" you find a "shared.h", and there is the library itself: "shared". (In the "shared/build" folder there will be also a "bin" directory with device and simulator names containing "debugFramework" and similar structures inside.)
OBJECTIVE SHARPIE
Download the "Objective Sharpie" tool
(https://learn.microsoft.com/en-us/xamarin/cross-platform/macios/binding/objective-sharpie/)
In order to create "ApiDefinitions.cs" from shared.h using
"sharpie" follow these steps:
Open a Termimal (Command-line) session.
Change to the directory where "shared" is located.
Type:
sharpie bind --output=./SharpieOutput --namespace=Shared --sdk iphoseos15.5 -scope ./shared ./shared/build/xcode-frameworks/Debug/iphonesimulator15.5/shared.framework/Headers/shared.h
(please replace "iphoneos15.5" by the correct SDK and "Debug/iphonesimulator15.5" by the correct folder name)
You also can choose another namespace instead of "Shared". It will be specified in the ApiDefinitions.h.
If successful, a "ApiDefinitions.cs" will be in a new subfolder
"SharpieOutput".
VISUAL STUDIO / XAMARIN
Use Visual Studio 2019 or 2022 or higher.
Create a new Solution, say, "MyApp".
"MyApp" should contain four projects: "MyApp", "MyApp.Android",
"MyApp.iOS".
Here, we don't talk about "MyApp.Android".
Right-click on the solution name and add a "New Project". Choose "iOS - Library - Bindings Library". Its name may be "MyApp.iOS.Binding".
Replace the ApiDefinitions.cs by that that has been created in the precding step.
Add the "shared" library (created by XCode in one of the steps above) as a "Native Library".
Right-click on ApiDefinitions.cs and change "Build action" =
"ObjcBindingApiDefinition".
When you now open ApiDefinitions.cs, you'll probably see a lot of errors and marked lines. They may be handled as follows:
For the "[Verify]" attribute, please check here: https://learn.microsoft.com/en-us/xamarin/ios/platform/binding-swift/walkthrough#build-a-binding-library , section 5.
If "NativeHandle" creates a compiler error, please add at the top:
#if !NET
using NativeHandle=System.IntPtr;
#endif
You may remove "using" with the shared module ("using shared")
If you encounter errors like "Cannot declare instance members in a static class (CS0708) and "static classes cannot implement interfaces" (CS0714): try to comment out or remove the attribute "[Category]".
"[Unavailable (PlatformName.Swift)]" may be removed if yielding an error.
Handle typed classes resp. Interfaces with "<T>". For example, the "<T>" attribute should be added to some interfaces representing typed classes. In some cases special handling is necessary.
CS0246: In some cases, when an element cannot be found, an attribute "[BaseType(typeof(SharedBase))]" may help (assuming that the interface SharedBase is defined at the beginning of this file).
If, during a build run, there are warnings CS8767 ("… hides inherited member"), add the attribute [Override] above these members. For "New()", however, add "[New]" instead.
In case of linker errors MT5211 "Native linking failed, undefined Objective-C class …", add the attribute "[Protocol]" in front of the interface definition:
[BaseTye (typeof (NSObject))]
[Protocol]
public interface MyInterface { … }
Other compiler / linker errors (e.g. " … was built for newer iOS version (…) than being linked …" possibly can result in warnings after that.
The "MyApp" project contains all platform independent code. Those classes which contain platform dependent parts should be defined as interfaces.
"MyApp.Android" and "MyApp.iOS" should implement these interfaces. For "MyApp.iOS", "MyApp" and "MyApp.iOS.Binding" should be added as References. The classes implementing those interfaces now can use the interfaces defined in ApiDefinitions.h.
End of instructions.
I have posted the same question in another forum - https://learn.microsoft.com/en-us/answers/questions/875957/use-business-code-for-android-and-ios-written-in-k.html - and I have posted a possible answer, see the answer of Jul 19, 2022. Spoiler: yes, it is possible, but not directly, and it is complicated.
I have an Android native library (C++ code base) called:
libserverapp.so
And I cannot get the Android build to find it:
"DllNotFoundException: serverapp"
I am using an internal build system, but when I parse the output of the build process, I can see many calls of the form:
android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-g++.exe -march=armv7-a
After building my Android app, I inspect the resulting APK (renaming to .zip and extracting), and can see my library file here:
lib/armeabi-v7a/libserverapp.so
I can confirm that "ARMv7" is the target architecture in the Android Player settings, and I access the library, in C#, via:
[DllImport("serverapp", CallingConvention = CallingConvention.Cdecl)]
private static extern void run_sim(StringBuilder matchInput, StringBuilder results, int randomSeed);
I have built a Windows DLL of the C++ code, to use in the Editor, and everything works great. However, when I move to Android, the .so cannot be found. The import settings for libserverapp.so are:
Platform: Android; CPU: ARMv7; Path: Assets/Plugins/Android/libserverapp.so; Type: Native
Given that the final APK includes the .so where I expect it to be (lib/armeabi-v7a/), I assume my Unity settings are correct? Also, I am not using IL2CPP for the Android build.
Finally, when I do an object dump of the library file (using arm-linux-androideabi-objdump.exe), the file format of the library file is "elf32-littlearm".
I feel that the issue here is simply finding the .so, not the functionality within it. Any ideas on what's going on here?
Thanks!
I ended up solving the problem. I mentioned that was using an internal build system. Well, there seems to be a bug in it. I ported things over to official Android NDK makefiles, and then it "just worked". So in this case, the library could be found, but its contents weren't valid.
is there someone who has experience with pyqtdeploy and adding external modules? I am currently using pyqtdeploy (version 1.2) together with PyQt 5.5.1 to write an application that can be deployed to an Android device. Without any external modules, the freezing with pyqtdeploy works pretty well. However, I am not really sure how I can add external modules (not pure Python ones) to my application.
In particular, I want to add the external module pycrypto. Therefore, I downloaded the pycrypto sourcecode, compiled it with the Android toolchain (from the Android NDK) and now I have a bunch of *.py and *.so files. How can I add them to my application?
My initial attempt was to add the *.py and the *.so files (so basically the whole pycrypto module) to the "Other Packages" tab in pyqtdeploy.
But now, when I import something pycrypto related in my application (from Crypto.Cipher import AES) i get the following error message:
File: ":/Crypto/Cipher/_AES.py", line 20 in __bootstrap__
TypeError: 'NoneType' object is not callable
The _AES.py file where the error is thrown, looks like this:
def __bootstrap__():
global __bootstrap__, __loader__, __file__
import sys, pkgutil, imp
__file__ = pkgutil.get_data(__name__,'_AES.cpython-34m.so')
__loader__ = None; del __bootstrap__, __loader__
imp.load_dynamic(__name__,__file__)
__bootstrap__()
At first I thought, that the *.so filename was just wrong and therefore, I got the NoneType Error, so I changed the filename in _AES.py to something other like 'test.so'. Surprisingly, now, I get a different error message than before:
File ":/pkgutil.py" line 629, in get_data
ImportError: qrcimporter: error opening file :/Crypto/Cipher/test.so
Ok, so the filename should be fine, right? But why do i get the 'NoneType` error message? What am I doing wrong? Is this the right way to accomplish this?
Any help is highly appreciated. I am pretty sure, that i'm only one small step away from getting this thing to work, but I can't figure out what i'm doing wrong.
Thanks!
I have an XML file that contains some config data for my Android App. In it there is config info that can be used for development and production. E.g. the link to our api can be set as follows:
For production:
<api>api.example.com</api>
For development:
<api>dev.example.com</api>
I keep this config file under /assets/app-config.xml
It is quite a hassle to keep having to remember which setting I have in the XML. Is there a way to automatically configure eclipse/ android so that it uses the production for runtime (export etc.) and the development when in debug mode.
Define multiple resources and use BuildConfig.DEBUG to conditionally get a resource or another:
<string name="url_api">api.example.com</string>
<string name="url_api_dev">dev.example.com</string>
When extracting the resource:
getString(BuildConfig.DEBUG ? R.string.url_api_dev : R.string.url_api);
This constant is set to true as long as you run from Eclipse. When you select the Export Signed Application Package option, it will be set to false.
If you use this method, it is a good idea to be aware of this bug.
Customize your build using ANT
Please refer the following link for more information
http://playaprogrammer.blogspot.com/2013/01/android-build-configuration-tutorial.html
I use this to create test and production builds from single source. You can have different configurations for development, QA, Production...
this is related to my previous question. I'm trying to build Phone application from android 4.0.4 using maven (I'm adding framework_intermediates as dependency, so internal apis problems are solved), and I ran into this problem. Some parts of the logs are as follows:
Phone/src/com/android/phone/CallNotifier.java:[601,32] cannot find symbol
symbol : variable EventLogTags
(the corresponding line in CallNotifier.java is: EventLog.writeEvent(EventLogTags.PHONE_UI_MULTIPLE_QUERY); )
Phone/src/com/android/phone/InCallScreen.java:[723,28] cannot find symbol
symbol : variable EventLogTags
(the corresponding line in InCallScreen.java is: EventLog.writeEvent(EventLogTags.PHONE_UI_ENTER); )
So... it cannot find the class EventLogTags. There is actually a file Phone/src/com/android/phone/EventLogTags.logtags which has the following contents:
# See system/core/logcat/event.logtags for a description of the format of this file.
option java_package com.android.phone;
70301 phone_ui_enter
70302 phone_ui_exit
70303 phone_ui_button_click (text|3)
70304 phone_ui_ringer_query_elapsed
70305 phone_ui_multiple_query
Apparently, this file tells the system to use some particular tags to log important events in the system. I did a full grep, but could not find any file which defines the values PHONE_UI_ENTER, PHONE_UI_MULTIPLE_QUERY, etc. These are just logs, so I could just comment out these and get it working. But I don't want to do this because I need to build this inside the entire aosp later on. So my question is, how do I get this to compile using maven, without modifying any file?
The Android build system code-generates a Java class out of .logtags files if needed. See: https://github.com/android/platform_build/blob/master/core/base_rules.mk
You will need to decipher the make rules and run that code generation yourself, I imagine.