How Android handle multiple R.java? - android

I'm making couple of Android library apps for a project. To simplify the question, let's say I have two libraries(utilLib, screenLib) in this project(now will be referred to as app).
There's String resource with the same name inside each project but with different values. Like this:
utilLib
<string name="app_version">1.0</string>
<string name="hello">UtilLib Hello</string>
screenLib
<string name="app_version">0.7a</string>
<string name="hello">ScreenLib Hello</string>
app
<string name="app_version">0.1</string>
I realized that I can refer to the string using com.package.R but what if my code looks like this what will show up?
<!-- language: java -->
import com.app.R;
...
private void checkValue(){
String version = getString(R.app_version);
Log.d(TAG, "version: " + version); // 0.1 show be here
String hello = getString(R.hello);
Log.d(TAG, "Hello: " + hello); // <---- ? ('UtilLib Hello' or 'ScreenLib Hello')
}
I am trying to make modular build here but don't fully understand how Android prioritize its R.java to use. Has anyone had experienced with this?

Log.d(TAG, "version: " + version); // 0.1 show be here
Reason quoting from official dev guide Managing Projects - Library Projects:
When you build an application that depends on a library project, the SDK tools compile the library into a temporary JAR file and uses it in the main project, then uses the result to generate the .apk. In cases where a resource ID is defined in both the application and the library, the tools ensure that the resource declared in the application gets priority and that the resource in the library project is not compiled into the application .apk. This gives your application the flexibility to either use or redefine any resource behaviors or values that are defined in any library.
Log.d(TAG, "Hello: " + hello); // <---- ? ('UtilLib Hello' or 'ScreenLib Hello')
This is determined by library project priority.
Quoting from official dev guide Managing Project -Library Projects:
Resource conflicts
Since the tools merge the resources of a library project with those of a dependent application project, a given resource ID might be defined in both projects. In this case, the tools select the resource from the application, or the library with highest priority, and discard the other resource. As you develop your applications, be aware that common resource IDs are likely to be defined in more than one project and will be merged, with the resource from the application or highest-priority library taking precedence.
Quoting from official dev guide From Eclipse with ADT - Referencing a library project:
If you are adding references to multiple libraries, note that you can set their relative priority (and merge order) by selecting a library and using the Up and Down controls. The tools merge the referenced libraries with your application starting from lowest priority (bottom of the list) to highest (top of the list). If more than one library defines the same resource ID, the tools select the resource from the library with higher priority. The application itself has highest priority and its resources are always used in preference to identical resource IDs defined in libraries.
Quoting from official dev guide From the Command Line - Referencing a Library Project:
If you are adding references to multiple libraries, note that you can set their relative priority (and merge order) by manually editing the project.properties file and adjusting the each reference's .n index as appropriate. For example, assume these references:
android.library.reference.1=path/to/library_projectA
android.library.reference.2=path/to/library_projectB
android.library.reference.3=path/to/library_projectC
You can reorder the references to give highest priority to library_projectC in this way:
android.library.reference.2=path/to/library_projectA
android.library.reference.3=path/to/library_projectB
android.library.reference.1=path/to/library_projectC
I can't find any word that can explain this more clear than official dev guide.

you will have to import com.screenLib.R and com.utilLib.R
In your code it should probably throw an error "cannot resolve hello"
Lemmme know if this is right!!!!

Related

Is it possible to use business code for Android and iOS written in Kotlin in a multiplatform Xamarin application?

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.

Two ane file conflict in one flex mobile application

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

Cannot compile system app (Phone) using maven - EventLogTags cannot be resolved

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.

Reference an integer resource for Android manifest versionCode

In my Android app I:
generate an incrementing build number (integer) using a script as part of my build (uses Integer from SVN revision)
I generate an Android resource file with it defined as an integer:
399
I show that on the UI using the resource generated above
I reference the integer in the Manifest for the versionCode element
All that works fine, but when I attempt to upload to Market I get this error:
"The file is invalid: ERROR getting 'android:versionCode' attribute: attribute is not an integer value "
Question:
For Market, does the versionCode have to be a "literal" integer directly inside the manifest, or is there some way to reference an externally generated integer and not be touching my manifest all the time (manually or automatically).
thanks
(BTW: I have just realized that scheme might cause me issues with patch releases, so I will probably generate a bigger number or something, but would still like the answer to this question)
In the end, this is what I have done:
I create a tag in my version control system with the numbe rof the release in this format
X.YY.ZZ where they are all integers, like 1.20.00, and reserve the last two digits for unplanned patch releases maybe made on a branch after a later release is made....
So if I release 1.20.00 then 1.23.00, I can still go back and do a patch release to 1.22.00 called 1.22.01.
I have a build step that gets the tag name and generates a string resource "1.22.00" for Android that I use in the UI. It also generates it as a number 12200 and I use this as the version number.
BUT, I don't try and include this version number directly in the manifest, I set it for the package by setting an ant property for version code that the ant build picks up if defined and uses to create the .apk.
So I get an always increasing integer for Android Market, but a user with an older version can install a patch release, but you cannot install a patch release if you have a newer official release.
i.e. if you have 1.20.00 you can install patch 1.20.01, but if a user has moved onto 1.23.00 they cannot install the 1.20.01 patch...
To set the property you can use;
project.setProperty("version.name", versionName);
project.setProperty("version.code", versionCode);
if those properties are set, then the Android build system (both old and newer) will pick-up the property value and use it, no need to do anything else special.
Just make sure you set it using one of the pre-build/pre-compile ant extension points.
In the new build system (Platform Tools >= 12) in custom_rules.xml I have added
<project name="custom" default="help">
<import file="build_info.xml" />
<target name="-pre-build" depends="build-info" />
</project>
where build_info is my own ant project that calculates the version name/number from the Tag name (if you are building in a tag....).
From everything I've read, Google Play currently requires android:versionCode to be a 32-bit integer, not a resource. Like you, I also initialize android:versionCode with an #integer resource.
To work around the market's limitation, our build script parses the #integer value and injects it directly into android:versionCode for release builds. This was a simple solution for us. There's far more involved ways to achieve this using ant.properties and the build.xml -pre-build option, however, that is beyond my needs.
For more on that, see:
Reference an integer resource for Android manifest versionCode
https://groups.google.com/d/msg/android-developers/1dt0yxyNPsk/c9c6PlG84iwJ

How to build Android without the phone application?

i'm trying to get android running on a gumstix overo system.
since i'm not planning to use the final "product" as a phone, i asked my self if it is possible to exclude applications like the phone/dialer-app from the kernel build-process (any config parameter probably?)
Just remove (or comment) these lines:
<project path="packages/apps/Phone" name="platform/packages/apps/Phone" />
<project path="packages/apps/VoiceDialer" name="platform/packages/apps/VoiceDialer" />
(and others if needed) from the platform manifest (default.xml) :
https://android.googlesource.com/platform/manifest/+/master/default.xml
Removing the app declarations in the repo manifest did not work for me, as there are other libraries that reference them that then fail to compile. The build system approach to this problem is to create/modify your product definition makefile to not include the specific apps.
So, for the overo you probably already have a products/overo.mk product file. You can manually set the PRODUCT_PACKAGES variable to which applications you want to ship. You will also want to take a look at the PRODUCT_POLICY variable, as it defines sets of applications for your product type.
It can take some fiddling to get everything to build correctly, due to interdependencies between applications, but the Android build output does a pretty good job of explaining the problems when they arise.

Categories

Resources