Currently our Xamarin Android app (PCL) is huge in my opinion, even in release mode. I suspect it is due to supported architectures. Currently we have them all selected. Does anyone know if we have to select all of these? We are not using the Android NDK at all as well.
I will copy part of my answer from here.
Make sure you are at least checking the following architectures: armeabi-v7a and x86. You could do the other three but we do not since we use LLVM compiling in release mode, which is not compatible with the 64 bit architectures (except for armeabi, which is deprecated). The good thing about that is that all of the 64 bit architectures can still use 32 bit builds so they all still get covered if you check those 3.
So I would just check those 3 unless you have a specific reason to check the other ones. We have had 0 problems installing our app on devices using those 3 only.
On a side note, turning on LLVM compiling and optimizing your icons/images will help with the final APK size.
*Edit: Since writing this we ran into a bug only on certain devices (Android Nexus 9) which leads to app crashes when launching the app. The solution is to check the arm64-v8a architecture. This will probably increase app size so weigh the pros and cons and see how much of a difference it makes in your APK size after including the architecture or split your APK for each architecture if necessary.
No you do not have to select all of them. You can create an .apk per ABI if you wanted to to reduce the size of your .apk. Note: The encouraged method is that you develop and publish a single .apk. However this is not always practical, and sometimes it's better to create separate ones. Although this answer only goes into depth about different CPU Architectures (ABI), you could also create different .apk for screen size, device features, and API levels.
https://developer.xamarin.com/guides/android/advanced_topics/build-abi-specific-apks/
http://developer.android.com/google/play/publishing/multiple-apks.html
I would recommend grabbing a tool like WinDirStat(https://windirstat.info/) or Disk Inventory X(http://www.derlien.com/) to investigate why your .apk is so large. You might find other reasons why your .apk is large such as resources(images, raw files), assemblies, etc.
Related
I have a Xamarin Forms app that is currently on the App Store that I built and submitted in October 2016 (with what I assume was the latest versions of Xamarin Studio and Xamarin.iOS back then). The app has a size of 50 mb on the App Store.
After doing a few updates to the app, I build it now (AppStore config, then Archive) and the size is 82 mb. Confused by this balloon in size, I switched back to the git tag of the version that is currently in the App Store. I can build the same exact tag/version/code for that October 2016 release and it's App Store size is now 80 mb.
I am using the latest Xamarin Studio (6.3 build 863), Xamarin.iOS (10.8.0.175), etc.
Why has the size grown by 60%? No application code or libraries have changed, only newer versions of Xamarin Studio and Xamarin.iOS. How do I figure out what is going on here? I can do an Add-Hoc build on my device and see that is only taking up ~55 mb, very close to what I see from the App Store.
Also, note that I am not comparing the .ipa size. I am comparing the "Estimated App Store Size" shown from the archive screen in Xamarin Studio after archiving a build. The same size difference is reflected after submitting the signed build via application loader to iTunes Connect and verifying from iTunes Connect > Activity > All Builds > App Store File Sizes.
Update Sept 5th 2017
Not sure what changed but now with the latest version of Xamarin iOS, Version: 10.12.0.20 (just updated), my app size is now back down in the 60mb range... Didn't change anything else.
I can do an Add-Hoc build on my device and see that is only taking up ~55 mb,
You likely have some different options between your configuration, e.g.
managed linker settings, e.g. Don't link versus Link SDK;
targeted architectures, e.g. armv7+arm64 versus armv7+armv7s+arm64;
How do I figure out what is going on here?
Compare your build logs, in particular the options given to the mtouch tool. That will generally pinpoint the difference quickly.
I am comparing the "Estimated App Store Size"
Always compare the IPA (file) size. The algorithm to guess the final size is known to be often (very) wrong. The estimation also comes from Apple's tools so they will vary with the version of Xcode you're using (which is unlikely to be identical to the one you used last fall).
Side note: the final size is even trickier to guess when bitcode is enabled (which is only for tvOS and watchOS builds right now).
My guess is that xamarin is packing a lot of unneeded stuff, maybe old images or similar that you are no longer using. I have experienced that myself.
Go to you project folder and delete everything in the obj folder
<myproject>/iOS/obj/
Usually you will see two folders in there: iPhone and iPhoneSimulator.
Delete those and build everything again, there's a good chance that will solve it
Are you using the same version of Xamarin to build your code. I am willing to bet that is the issue. Something changed in how Xamarin builds apps since the last time you released it and is blowing up your app build size.
If you actually have the same code you released back then do you know what version of Xamarin you used back then? Honestly since the only thing that's changed is the Xamarin compiler it is most definitely the issue.
There are four things to do:
DELETE bin and obj folder from client project
CHANGE architecture to only support 64
CONFIGURE the linker.
Best is to try and build your app with linker active, but the more nuget packages you use, the less likely this is
and most importantly:
Set your build config to RELEASE and not DEBUG
(if you forget that, stores will accept your app but size can easily be doubled or even trippled)
This is how the minimal setup should look like:
Then dont forget that XAMARIN adds libraries like crazy to your app. I once read that the smallest app with NO content at all is at least 7 MB. This only gets larger with each package and each new dependency.
Backgrond
I am very experienced in C and pretty new to Android and Java, but this is rather environmental issues that programming.
I have developed an administrative application in ANSI-C to be ported to any OS, just adding a UI in OS-dependent code. Well it uses quite some memory, especially for huge user files. I have a working Win32 program, trying to make an Android app using Android Studio with NDK.
Android studio bundle NDK installation works fine
I have installed and made a Win7 ultimate Android Studio 1.3 with bundle NDK and made compiling and running the ActionbarStyled (non NDK) hello-jni (NDK) sample in the emulators, smooth and nice. I also in the emulator been successfully running Hello-jni sample with a bunch of extra c-files (not called, at present just garbage, compiled without errors, in this step)
Then I tried to connect my Samsung TAB3 SM-T110 template (one need a Win7 Samsung driver SAMSUNG_USB_Driver_for_Mobile_Phones.zip) to my Win7 and tried it. ActionbarStyled sample works just fine. So does the Hello-JNI sample.
But
Running Hello-jni sample with a bunch of extra c-files I get this error message:
Error while starting native debug session: java.lang.IllegalArgumentException: Unable to find process for com.example.hellojni on device samsung-sm_t110-47900bc50c0c3100
I try to understand what is the issue? Is it lack of memory, the Samsung is full of active running apps, the emulator obviously not.
What makes the Samsung unit to halt the application? Error message is not that describing?
Some more questions supporting handling this kind of issues
We are talking about Android studio 1.3 bundle NDK, how much from earlier setups (in articles) are applicable for this new future NDK standard use?
Memory?
Running the pure Hello-jni sample I have about 6Mb memory (where 5Mb are used), that is pretty poor for my needs, is there something I need to do have my app getting more memory allocated? Is the error message due to running out of memory?
How large Android Apps are possible to do? Are we in a world like the 8-bit DOS 64Kb segment business again? I know it from past but that isen't the case? And if need to know to handle it. The Library for unrestricted heap memory for bitmaps using NDK on Android question is interesting to read, but here we are talking about the jni (C-)code rather than java.
Compiler optimisation?
I have some really huge C-files due to that they are machine generated converting an XML library of documents to C-code (made a program writing C-code from the XSD definitions). In an application I most of the time use only say 5% of all the C-function, the rest are in Windows dev studio/compiler optimised away. Certainly I can reorganise my source code to quite some extra work, but I need to know. How is the optimisation in the Android Studio NDK support?
Thing is in this test no extra C-functions are called except the same regular as in the hello-jni sample. Actually the compiler should make exactly the same in both cases (the modified and the original hello-jni). But obviously it don't. Please explain a bit more how the environment works so I know?
General interest
I tried to find any spot in the Android developers that describe things like compiler behaviour, memory management and environment (the Java handles such completely different, but in C-programming on need to be aware). I think for NDK use it would be interesting getting a good answer here, for the general understanding of the environment, somewhere in the Android developer pages, rather than here. That also includes how the compiler optimises in different situations. But also how to make environmental settings.
I have an embedded device with WinCE 6.0 as OS. The manufacturer provides an IDE for 3rd party development to it. The IDE pretty much allows nothing else than
.NET 3.5 Compact Framework scripting that's invoked from various events from the main application
Adding files to the device.
The included mediaplayer seems to be using DirectShow and the OS has media codec only for mpeg-1 encoded video playback. My goal is to to be able to play media encoded with some other codecs as well inside that main application.
I've already managed to use DirectShowNETCF (DirectShow wrapper for .NET Compact Framework) and successfully playback mpeg-1 encoded video.
I'm totally new with this stuff and I have tons of (stupid) questions. I'll try to narrow them down:
The OS is based on WinCE, but as far as I've understood, it's actually always some customized version of it (via Platform Builder). Only "correct way" of developing anything for it afterwards is to use the SDK the manufacturer usually provides. Right? In my case, the SDK is extremely limited and tightly integrated into IDE as noted above. However, .NET CF 3.5 is capable for interop so its possible to call native libraries -as long as they are compiled for correct platform.
Compiled code is pretty much just instructions for the processor (assembler code) and the compiler chooses the correct instructions based on the target processor setting. Also there's the PE-header that defines under which platform the program is meant to be run. If I target my "helloworld.exe" (does nothing but returns specific exit code) to x86 and compile it with VC, should it work?
If the PE-header is in fact the problem, is it possible to setup for WINCE without the SDK? Do I REALLY need the whole SDK for creating a simple executable that uses only base types? I'm using VS2010, which doesn't even support smart device dev anymore and I'd hate to downgrade just for testing purposes.
Above questions are prequel to my actual idea: Porting ffmpeg/ffdshow for WinCE. This actually already exists, but not targeted nor built for Intel Atom. Comments?
If the native implementation is not possible and I would end up implementing some specific codec with C#...well that would probably be quite a massive task. But having to choose C# over native, could I run into problems with codec performance? I mean.. is C# THAT much slower?
Thank you.
I've not seen an OEM that shipped their own IDE, but it's certainly possible. That shouldn't change how apps can created, however. It's possible that they've done a lot of work to make sure only things from their IDE work, but that would be a serious amount of work for not that much benefit, so I'd think it's unlikely.
As for your specific questions:
The OS is Windows CE, not "based on" it. The OS is, however, componentized, so not all pieces are going to be available. An SDK generally provides a mechanism to filter out what isn't available. You can actually use any SDK that targets the right processor architecture, but if your app calls into a library for something that isn't in the OS, then you'll get at the very least an error. For managed code this is all not relevant because the CF isn't componentized. If it's there, and CF app can run (and if it's not, you can often install it after the fact). This means that if the platform supports the CF, then you can write a CF app and run it. That app can then call native stuff via P/Invoke (unless, of course, the OS creator decided to add security to prevent that. This is possible in the OS, though I've never seen it implemented).
Yes, compiled code is just "instructions". For native, yes, they are processor instructions. For managed, they are MSIL instructions that the managed runtime in turn converts to processor instructions at JIT time. If your target is an ARM platform, you cannot use an x86 compiler. Broadly speaking, you need to use the correct Microsoft compiler that support Windows CE, and call that compiler with the proper switches to tell it not only the processor architecture, but also the target OS because the linking that needs to be done will be different for OS-level APIs and even the C runtimes. The short of this is that for your platform, you need to use Visual Studio 2008 Pro.
For native apps, you need some SDK that targets the same OS version (CE 6.0) and processor architecture (e.g. ARMv4I). Having it match the OS feature set is also useful but not a requirement. For managed code, you can just use the SDKs that ship with Studio because managed code is not processor-dependent. Still, you have to go back to Studio 2008 because 2010 doesn't have any WinCE compilers.
If you've found an existing library, then you can try to use it. Things that might impede your progress are A) it's unlikely to use an SDK you have so you probably have to create new project files (painful, but workable) and B) if it uses features not available in your OS, then you'd have to work around those. If you're missing OS features, you're probably out of luck but if it already has a media player and codec, I suspect you'll be ok.
Don't implement this in managed code. Seriously, just don't do it. Could you? Yes. Performance could probably be made to be nearly the same except to avoid GC stuttering you're going to have to basically create your own memory manager. The amount of work involved in this path is very, very large.
I have the same problem with Xcode Cannot Run on the Selected Destination
The destination does not support the architecture for which the
selected software is built. Switch to a destination that supports that
architecture in order to run the selected software.
I tried the solutions there and it doesn't work.
So I'll try to do something more reasonable.
What does the error means anyway? What is Xcode trying to say when it says to switch to a destination that supports that architecture? Where is the archtecture specified? What software? What is the problem?
While solutions may be nice what I am looking for is understanding of what it really means.
The project used to work
The project still work in real iPhone but not simulator
I used the newest facebook SDK. However, it run before even after the SDK. It's after I clean project it doesn't work.
While I don't have a solution for your problem, I can answer your question, namely, what does Xcode thinks is wrong and what does the error means.
So, the destination is actually your simulator in this case (could be the iPhone as well, if you're building for it). The architecture is decently explained here. What you need to understand is that in order for a software to run on a specific architecture it needs to be build for it(or assembled for it, to be more precise). That means that for the same software the CPU instructions are not the same for an iPhone (which has an ARM CPU) as they are for your iMac (which is x64).
Now, with the above in mind, what Xcode is trying to say is that you are trying to build the wrong architecture for your simulator and you should switch to a different destination that supports that architecture (as you mentioned, you can build just fine on the iPhone, which is a different architecture) in order for the software to run.
It could be an Xcode bug or a misconfiguration. You're probably better off creating a new project and copy all your classes into it than hunting it down.
You'll be happy to know this problem has a very simple solution. Select Info.plist in your project navigator tree and make sure it is not assigned to a target. I have confirmed this is the correct solution. If building for iOS 6 or earlier you may also need to add armv6 to supported architectures
Short question: How do you take two apps, one for intel and the other ppc, and package them into one Universal Binary?
My current thoughts on this problem:
I have read though the apple developer documentation on universal binaries and haven't been able to find an answer so it may not be possible.
Due to reasons I won't go into here I have two apps of my program (apposed to using xtools to compile the binary universally once), one for Intel Macs and the other for Mac >=10.3.9 running on PPC. Sharing resources is a non-issue.
I could put both MyProg_intel.app and MyProg_ppc.app into one zip and distribute it that way; but that may result in confusion for many people who I will be distributing my program to.
See the lipo tool. It will let you stitch together your PPC and i386 binaries.
Also, sometimes separate targets for different architectures can be avoided by using conditional build settings in Xcode. This is useful if you need to link against a different binary library for each architecture, for example.
Check out the man page for lipo. I believe you can use -create to take multiple input files and create a single output file with multiple architectures.
Apple's developer web site has an article on Building an Open Source Universal Binary that explains how to use Xcode to 'package' a Universal Binary using build scripts. This is probably your best road to sanity. You could use lipo, but in the long run if you are going to update and maintain your application, having an Xcode project that does the magic for you is going to take up a lot less of your time.
In order to create a Universal Binary, you have to use Xcode and select both Intel and PPC target architectures. As far as I know, you can't just stuff two different binaries into one .app ex post facto.