@nativescript/core 9.0.0-next-09-27-2025-18063560861 → 9.0.0-next-10-06-2025-18277360121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/platforms/android/include.gradle +51 -0
- package/platforms/android/java/org/nativescript/Process.java +59 -0
- package/platforms/android/java/org/nativescript/widgets/AbsoluteLayout.java +88 -0
- package/platforms/android/java/org/nativescript/widgets/AnimatorHelper.java +61 -0
- package/platforms/android/java/org/nativescript/widgets/Async.java +1356 -0
- package/platforms/android/java/org/nativescript/widgets/BorderDrawable.java +936 -0
- package/platforms/android/java/org/nativescript/widgets/BottomNavigationBar.java +308 -0
- package/platforms/android/java/org/nativescript/widgets/BoxShadowDrawable.java +175 -0
- package/platforms/android/java/org/nativescript/widgets/CSSValue.java +34 -0
- package/platforms/android/java/org/nativescript/widgets/CommonLayoutParams.java +456 -0
- package/platforms/android/java/org/nativescript/widgets/ContentLayout.java +85 -0
- package/platforms/android/java/org/nativescript/widgets/CustomTransition.java +135 -0
- package/platforms/android/java/org/nativescript/widgets/CustomTypefaceSpan.java +44 -0
- package/platforms/android/java/org/nativescript/widgets/Dock.java +15 -0
- package/platforms/android/java/org/nativescript/widgets/DockLayout.java +185 -0
- package/platforms/android/java/org/nativescript/widgets/FileHelper.java +815 -0
- package/platforms/android/java/org/nativescript/widgets/FlexLine.java +177 -0
- package/platforms/android/java/org/nativescript/widgets/FlexboxLayout.java +2769 -0
- package/platforms/android/java/org/nativescript/widgets/FragmentBase.java +14 -0
- package/platforms/android/java/org/nativescript/widgets/GridLayout.java +1172 -0
- package/platforms/android/java/org/nativescript/widgets/GridUnitType.java +10 -0
- package/platforms/android/java/org/nativescript/widgets/HorizontalScrollView.java +256 -0
- package/platforms/android/java/org/nativescript/widgets/ImageView.java +423 -0
- package/platforms/android/java/org/nativescript/widgets/ItemSpec.java +56 -0
- package/platforms/android/java/org/nativescript/widgets/LayoutBase.java +98 -0
- package/platforms/android/java/org/nativescript/widgets/LinearGradientDefinition.java +46 -0
- package/platforms/android/java/org/nativescript/widgets/Orientation.java +9 -0
- package/platforms/android/java/org/nativescript/widgets/OriginPoint.java +74 -0
- package/platforms/android/java/org/nativescript/widgets/ScrollSavedState.java +63 -0
- package/platforms/android/java/org/nativescript/widgets/SegmentedBarColorDrawable.java +27 -0
- package/platforms/android/java/org/nativescript/widgets/StackLayout.java +231 -0
- package/platforms/android/java/org/nativescript/widgets/StyleableTextView.java +50 -0
- package/platforms/android/java/org/nativescript/widgets/TabIconRenderingMode.java +6 -0
- package/platforms/android/java/org/nativescript/widgets/TabItemSpec.java +15 -0
- package/platforms/android/java/org/nativescript/widgets/TabLayout.java +451 -0
- package/platforms/android/java/org/nativescript/widgets/TabStrip.java +294 -0
- package/platforms/android/java/org/nativescript/widgets/TabViewPager.java +64 -0
- package/platforms/android/java/org/nativescript/widgets/TabsBar.java +443 -0
- package/platforms/android/java/org/nativescript/widgets/Utils.java +546 -0
- package/platforms/android/java/org/nativescript/widgets/VerticalScrollView.java +258 -0
- package/platforms/android/java/org/nativescript/widgets/ViewHelper.java +564 -0
- package/platforms/android/java/org/nativescript/widgets/WrapLayout.java +252 -0
- package/platforms/android/java/org/nativescript/widgets/image/AsyncTask.java +679 -0
- package/platforms/android/java/org/nativescript/widgets/image/BitmapOwner.java +17 -0
- package/platforms/android/java/org/nativescript/widgets/image/Cache.java +471 -0
- package/platforms/android/java/org/nativescript/widgets/image/DiskLruCache.java +970 -0
- package/platforms/android/java/org/nativescript/widgets/image/Fetcher.java +747 -0
- package/platforms/android/java/org/nativescript/widgets/image/Utils.java +58 -0
- package/platforms/android/java/org/nativescript/widgets/image/Worker.java +571 -0
- package/platforms/ios/src/TNSWidgets/Info.plist +26 -0
- package/platforms/ios/src/TNSWidgets/NSData+Async.m +42 -0
- package/platforms/ios/src/TNSWidgets/NSFileHandle+Async.m +82 -0
- package/platforms/ios/src/TNSWidgets/NSObject+Swizzling.m +68 -0
- package/platforms/ios/src/TNSWidgets/NSString+Async.m +51 -0
- package/platforms/ios/src/TNSWidgets/TNSLabel.m +42 -0
- package/platforms/ios/src/TNSWidgets/UIImage+TNSBlocks.m +77 -0
- package/platforms/ios/src/TNSWidgets/UIView+PassThroughParent.m +53 -0
- package/platforms/ios/src/TNSWidgets/UIView+PropertyBag.m +72 -0
- package/platforms/ios/src/module.modulemap +5 -0
- package/platforms/android/widgets-release.aar +0 -0
- package/platforms/ios/TNSWidgets.xcframework/Info.plist +0 -102
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers/NSCCrypto.h +0 -60
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers/TNSProcess.h +0 -29
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Info.plist +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Modules/module.modulemap +0 -6
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Info.plist +0 -20
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +0 -82
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/NSCCrypto.h +0 -60
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/NSData+Async.h +0 -24
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/NSFileHandle+Async.h +0 -22
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/NSString+Async.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/TNSLabel.h +0 -16
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/TNSProcess.h +0 -29
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/TNSWidgets.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/UIImage+TNSBlocks.h +0 -26
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Headers/UIView+PassThroughParent.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Modules/module.modulemap +0 -6
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/PrivateHeaders/NSObject+Swizzling.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/PrivateHeaders/UIView+PropertyBag.h +0 -18
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Resources/Info.plist +0 -52
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/NSCCrypto.h +0 -60
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/NSData+Async.h +0 -24
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/NSFileHandle+Async.h +0 -22
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/NSString+Async.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/TNSLabel.h +0 -16
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/TNSProcess.h +0 -29
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/TNSWidgets.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/UIImage+TNSBlocks.h +0 -26
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Headers/UIView+PassThroughParent.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Modules/module.modulemap +0 -6
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/PrivateHeaders/NSObject+Swizzling.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/PrivateHeaders/UIView+PropertyBag.h +0 -18
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Resources/Info.plist +0 -52
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/NSCCrypto.h +0 -60
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/NSData+Async.h +0 -24
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/NSFileHandle+Async.h +0 -22
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/NSString+Async.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/TNSLabel.h +0 -16
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/TNSProcess.h +0 -29
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/TNSWidgets.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/UIImage+TNSBlocks.h +0 -26
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Headers/UIView+PassThroughParent.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Modules/module.modulemap +0 -6
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/PrivateHeaders/NSObject+Swizzling.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/PrivateHeaders/UIView+PropertyBag.h +0 -18
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Resources/Info.plist +0 -52
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Info.plist +0 -20
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +0 -82
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +0 -82
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/NSCCrypto.h +0 -60
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/NSData+Async.h +0 -24
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/NSFileHandle+Async.h +0 -22
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/NSString+Async.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/TNSLabel.h +0 -16
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/TNSProcess.h +0 -29
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/TNSWidgets.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/UIImage+TNSBlocks.h +0 -26
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Headers/UIView+PassThroughParent.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Info.plist +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Modules/module.modulemap +0 -6
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/PrivateHeaders/NSObject+Swizzling.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/PrivateHeaders/UIView+PropertyBag.h +0 -18
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/_CodeSignature/CodeResources +0 -223
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Info.plist +0 -20
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +0 -82
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +0 -82
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/NSCCrypto.h +0 -60
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/NSData+Async.h +0 -24
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/NSFileHandle+Async.h +0 -22
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/NSString+Async.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/TNSLabel.h +0 -16
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/TNSProcess.h +0 -29
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/TNSWidgets.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/UIImage+TNSBlocks.h +0 -26
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Headers/UIView+PassThroughParent.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Info.plist +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Modules/module.modulemap +0 -6
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/PrivateHeaders/NSObject+Swizzling.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/PrivateHeaders/UIView+PropertyBag.h +0 -18
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Info.plist +0 -20
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +0 -82
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/NSCCrypto.h +0 -60
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/NSData+Async.h +0 -24
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/NSFileHandle+Async.h +0 -22
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/NSString+Async.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/TNSLabel.h +0 -16
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/TNSProcess.h +0 -29
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/TNSWidgets.h +0 -25
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/UIImage+TNSBlocks.h +0 -26
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Headers/UIView+PassThroughParent.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Info.plist +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Modules/module.modulemap +0 -6
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/PrivateHeaders/NSObject+Swizzling.h +0 -17
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/PrivateHeaders/UIView+PropertyBag.h +0 -18
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/_CodeSignature/CodeResources +0 -223
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Info.plist +0 -20
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +0 -82
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +0 -82
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers → src/TNSWidgets}/NSData+Async.h +0 -0
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers → src/TNSWidgets}/NSFileHandle+Async.h +0 -0
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/PrivateHeaders → src/TNSWidgets}/NSObject+Swizzling.h +0 -0
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers → src/TNSWidgets}/NSString+Async.h +0 -0
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers → src/TNSWidgets}/TNSLabel.h +0 -0
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers → src/TNSWidgets}/TNSWidgets.h +0 -0
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers → src/TNSWidgets}/UIImage+TNSBlocks.h +0 -0
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Headers → src/TNSWidgets}/UIView+PassThroughParent.h +0 -0
- /package/platforms/ios/{TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/PrivateHeaders → src/TNSWidgets}/UIView+PropertyBag.h +0 -0
|
@@ -0,0 +1,747 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2012 The Android Open Source Project
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
package org.nativescript.widgets.image;
|
|
18
|
+
|
|
19
|
+
import android.annotation.TargetApi;
|
|
20
|
+
import android.content.ContentResolver;
|
|
21
|
+
import android.content.Context;
|
|
22
|
+
import android.content.res.Resources;
|
|
23
|
+
import android.graphics.Bitmap;
|
|
24
|
+
import android.graphics.BitmapFactory;
|
|
25
|
+
import android.graphics.Matrix;
|
|
26
|
+
import android.net.Uri;
|
|
27
|
+
import android.os.Build;
|
|
28
|
+
import android.os.ParcelFileDescriptor;
|
|
29
|
+
import android.util.Log;
|
|
30
|
+
import android.util.TypedValue;
|
|
31
|
+
|
|
32
|
+
import androidx.exifinterface.media.ExifInterface;
|
|
33
|
+
|
|
34
|
+
import java.io.BufferedInputStream;
|
|
35
|
+
import java.io.BufferedOutputStream;
|
|
36
|
+
import java.io.ByteArrayInputStream;
|
|
37
|
+
import java.io.ByteArrayOutputStream;
|
|
38
|
+
import java.io.File;
|
|
39
|
+
import java.io.FileDescriptor;
|
|
40
|
+
import java.io.FileInputStream;
|
|
41
|
+
import java.io.FileNotFoundException;
|
|
42
|
+
import java.io.IOException;
|
|
43
|
+
import java.io.InputStream;
|
|
44
|
+
import java.io.OutputStream;
|
|
45
|
+
import java.net.HttpURLConnection;
|
|
46
|
+
import java.net.URL;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A simple subclass of {@link Worker} that fetch and resize images from a file, resource or URL.
|
|
50
|
+
*/
|
|
51
|
+
public class Fetcher extends Worker {
|
|
52
|
+
private static final int HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10MB
|
|
53
|
+
private static final String HTTP_CACHE_DIR = "http";
|
|
54
|
+
private static final int IO_BUFFER_SIZE = 8 * 1024;
|
|
55
|
+
|
|
56
|
+
private static int mDeviceWidthPixels;
|
|
57
|
+
private static int mDeviceHeightPixels;
|
|
58
|
+
|
|
59
|
+
private final File mHttpCacheDir;
|
|
60
|
+
private DiskLruCache mHttpDiskCache;
|
|
61
|
+
private boolean mHttpDiskCacheStarting = true;
|
|
62
|
+
private final Object mHttpDiskCacheLock = new Object();
|
|
63
|
+
private static final int DISK_CACHE_INDEX = 0;
|
|
64
|
+
|
|
65
|
+
private final String mPackageName;
|
|
66
|
+
private static Fetcher instance;
|
|
67
|
+
|
|
68
|
+
public static Fetcher getInstance(Context context) {
|
|
69
|
+
if (instance == null) {
|
|
70
|
+
instance = new Fetcher(context);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return instance;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Initialize providing a target image width and height for the processing images.
|
|
78
|
+
*
|
|
79
|
+
* @param context
|
|
80
|
+
*/
|
|
81
|
+
private Fetcher(Context context) {
|
|
82
|
+
super(context);
|
|
83
|
+
mHttpCacheDir = Cache.getDiskCacheDir(context, HTTP_CACHE_DIR);
|
|
84
|
+
mPackageName = context.getPackageName();
|
|
85
|
+
mDeviceWidthPixels = context.getResources().getDisplayMetrics().widthPixels;
|
|
86
|
+
mDeviceHeightPixels = context.getResources().getDisplayMetrics().heightPixels;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@Override
|
|
90
|
+
protected void initDiskCacheInternal() {
|
|
91
|
+
if (!mHttpCacheDir.exists()) {
|
|
92
|
+
mHttpCacheDir.mkdirs();
|
|
93
|
+
}
|
|
94
|
+
synchronized (mHttpDiskCacheLock) {
|
|
95
|
+
if (Cache.getUsableSpace(mHttpCacheDir) > HTTP_CACHE_SIZE) {
|
|
96
|
+
try {
|
|
97
|
+
mHttpDiskCache = DiskLruCache.open(mHttpCacheDir, 1, 1, HTTP_CACHE_SIZE);
|
|
98
|
+
if (debuggable > 0) {
|
|
99
|
+
Log.v(TAG, "HTTP cache initialized");
|
|
100
|
+
}
|
|
101
|
+
} catch (IOException e) {
|
|
102
|
+
mHttpDiskCache = null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
mHttpDiskCacheStarting = false;
|
|
106
|
+
mHttpDiskCacheLock.notifyAll();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@Override
|
|
111
|
+
protected void clearCacheInternal() {
|
|
112
|
+
super.clearCacheInternal();
|
|
113
|
+
synchronized (mHttpDiskCacheLock) {
|
|
114
|
+
if (mHttpDiskCache != null && !mHttpDiskCache.isClosed()) {
|
|
115
|
+
try {
|
|
116
|
+
mHttpDiskCache.delete();
|
|
117
|
+
if (debuggable > 0) {
|
|
118
|
+
Log.v(TAG, "HTTP cache cleared");
|
|
119
|
+
}
|
|
120
|
+
} catch (IOException e) {
|
|
121
|
+
Log.e(TAG, "clearCacheInternal - " + e);
|
|
122
|
+
}
|
|
123
|
+
mHttpDiskCache = null;
|
|
124
|
+
mHttpDiskCacheStarting = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@Override
|
|
130
|
+
protected void flushCacheInternal() {
|
|
131
|
+
synchronized (mHttpDiskCacheLock) {
|
|
132
|
+
if (mHttpDiskCache != null) {
|
|
133
|
+
try {
|
|
134
|
+
mHttpDiskCache.flush();
|
|
135
|
+
if (debuggable > 0) {
|
|
136
|
+
Log.v(TAG, "HTTP cache flushed");
|
|
137
|
+
}
|
|
138
|
+
} catch (IOException e) {
|
|
139
|
+
Log.e(TAG, "flush - " + e);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@Override
|
|
146
|
+
protected void closeCacheInternal() {
|
|
147
|
+
synchronized (mHttpDiskCacheLock) {
|
|
148
|
+
if (mHttpDiskCache != null) {
|
|
149
|
+
try {
|
|
150
|
+
if (!mHttpDiskCache.isClosed()) {
|
|
151
|
+
mHttpDiskCache.close();
|
|
152
|
+
mHttpDiskCache = null;
|
|
153
|
+
if (debuggable > 0) {
|
|
154
|
+
Log.v(TAG, "HTTP cache closed");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} catch (IOException e) {
|
|
158
|
+
Log.e(TAG, "closeCacheInternal - " + e);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The main process method, which will be called by the Worker in the AsyncTask background
|
|
166
|
+
* thread.
|
|
167
|
+
*
|
|
168
|
+
* @param data The data to load the bitmap, in this case, a regular http URL
|
|
169
|
+
* @return The downloaded and resized bitmap
|
|
170
|
+
*/
|
|
171
|
+
private Bitmap processHttp(String data, int decodeWidth, int decodeHeight, boolean keepAspectRatio) {
|
|
172
|
+
final String key = Cache.hashKeyForDisk(data);
|
|
173
|
+
FileDescriptor fileDescriptor = null;
|
|
174
|
+
FileInputStream fileInputStream = null;
|
|
175
|
+
DiskLruCache.Snapshot snapshot;
|
|
176
|
+
synchronized (mHttpDiskCacheLock) {
|
|
177
|
+
// Wait for disk cache to initialize
|
|
178
|
+
while (mHttpDiskCacheStarting) {
|
|
179
|
+
try {
|
|
180
|
+
mHttpDiskCacheLock.wait();
|
|
181
|
+
} catch (InterruptedException e) {
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (mHttpDiskCache != null) {
|
|
186
|
+
try {
|
|
187
|
+
snapshot = mHttpDiskCache.get(key);
|
|
188
|
+
if (snapshot == null) {
|
|
189
|
+
if (debuggable > 0) {
|
|
190
|
+
Log.v(TAG, "processBitmap, not found in http cache, downloading...");
|
|
191
|
+
}
|
|
192
|
+
DiskLruCache.Editor editor = mHttpDiskCache.edit(key);
|
|
193
|
+
if (editor != null) {
|
|
194
|
+
if (downloadUrlToStream(data, editor.newOutputStream(DISK_CACHE_INDEX))) {
|
|
195
|
+
editor.commit();
|
|
196
|
+
} else {
|
|
197
|
+
editor.abort();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
snapshot = mHttpDiskCache.get(key);
|
|
201
|
+
}
|
|
202
|
+
if (snapshot != null) {
|
|
203
|
+
fileInputStream = (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX);
|
|
204
|
+
fileDescriptor = fileInputStream.getFD();
|
|
205
|
+
}
|
|
206
|
+
} catch (IOException e) {
|
|
207
|
+
Log.e(TAG, "processHttp - " + e);
|
|
208
|
+
} catch (IllegalStateException e) {
|
|
209
|
+
Log.e(TAG, "processHttp - " + e);
|
|
210
|
+
} finally {
|
|
211
|
+
if (fileDescriptor == null && fileInputStream != null) {
|
|
212
|
+
try {
|
|
213
|
+
fileInputStream.close();
|
|
214
|
+
} catch (IOException e) {
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
Bitmap bitmap = null;
|
|
222
|
+
if (fileDescriptor != null) {
|
|
223
|
+
bitmap = decodeSampledBitmapFromDescriptor(fileDescriptor, decodeWidth, decodeHeight, keepAspectRatio,
|
|
224
|
+
getCache());
|
|
225
|
+
}
|
|
226
|
+
if (fileInputStream != null) {
|
|
227
|
+
try {
|
|
228
|
+
fileInputStream.close();
|
|
229
|
+
} catch (IOException e) {
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return bitmap;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private Bitmap processHttpNoCache(String data, int decodeWidth, int decodeHeight, boolean keepAspectRatio) {
|
|
236
|
+
ByteArrayOutputStreamInternal outputStream = null;
|
|
237
|
+
Bitmap bitmap = null;
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
outputStream = new ByteArrayOutputStreamInternal();
|
|
241
|
+
if (downloadUrlToStream(data, outputStream)) {
|
|
242
|
+
bitmap = decodeSampledBitmapFromByteArray(outputStream.getBuffer(), decodeWidth, decodeHeight,
|
|
243
|
+
keepAspectRatio, getCache());
|
|
244
|
+
}
|
|
245
|
+
} catch (IllegalStateException e) {
|
|
246
|
+
Log.e(TAG, "processHttpNoCache - " + e);
|
|
247
|
+
} finally {
|
|
248
|
+
if (outputStream != null) {
|
|
249
|
+
try {
|
|
250
|
+
outputStream.close();
|
|
251
|
+
} catch (IOException e) {
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return bitmap;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@Override
|
|
260
|
+
protected Bitmap processBitmap(String uri, int decodeWidth, int decodeHeight, boolean keepAspectRatio,
|
|
261
|
+
boolean useCache) {
|
|
262
|
+
if (debuggable > 0) {
|
|
263
|
+
Log.v(TAG, "process: " + uri);
|
|
264
|
+
}
|
|
265
|
+
if (uri.startsWith(CONTENT_PREFIX)) {
|
|
266
|
+
return decodeSampledBitmapFromContent(uri, mResolver, decodeWidth, decodeHeight, keepAspectRatio, getCache());
|
|
267
|
+
} else if (uri.startsWith(FILE_PREFIX)) {
|
|
268
|
+
String filename = uri.substring(FILE_PREFIX.length());
|
|
269
|
+
return decodeSampledBitmapFromFile(filename, decodeWidth, decodeHeight, keepAspectRatio, getCache());
|
|
270
|
+
} else if (uri.startsWith(RESOURCE_PREFIX)) {
|
|
271
|
+
String resPath = uri.substring(RESOURCE_PREFIX.length());
|
|
272
|
+
int resId = mResources.getIdentifier(resPath, "drawable", mPackageName);
|
|
273
|
+
if (resId > 0) {
|
|
274
|
+
return decodeSampledBitmapFromResource(mResources, resId, decodeWidth, decodeHeight, keepAspectRatio,
|
|
275
|
+
getCache());
|
|
276
|
+
} else {
|
|
277
|
+
Log.v(TAG, "Missing Image with resourceID: " + uri);
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
if (useCache && mHttpDiskCache != null) {
|
|
282
|
+
return processHttp(uri, decodeWidth, decodeHeight, keepAspectRatio);
|
|
283
|
+
} else {
|
|
284
|
+
return processHttpNoCache(uri, decodeWidth, decodeHeight, keepAspectRatio);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Download a bitmap from a URL and write the content to an output stream.
|
|
291
|
+
*
|
|
292
|
+
* @param urlString The URL to fetch
|
|
293
|
+
* @return true if successful, false otherwise
|
|
294
|
+
*/
|
|
295
|
+
public boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
|
|
296
|
+
disableConnectionReuseIfNecessary();
|
|
297
|
+
HttpURLConnection urlConnection = null;
|
|
298
|
+
BufferedOutputStream out = null;
|
|
299
|
+
BufferedInputStream in = null;
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
final URL url = new URL(urlString);
|
|
303
|
+
urlConnection = (HttpURLConnection) url.openConnection();
|
|
304
|
+
in = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE);
|
|
305
|
+
out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE);
|
|
306
|
+
|
|
307
|
+
int b;
|
|
308
|
+
while ((b = in.read()) != -1) {
|
|
309
|
+
out.write(b);
|
|
310
|
+
}
|
|
311
|
+
return true;
|
|
312
|
+
} catch (final IOException e) {
|
|
313
|
+
Log.e(TAG, "Error in downloadBitmap - " + e);
|
|
314
|
+
} finally {
|
|
315
|
+
if (urlConnection != null) {
|
|
316
|
+
urlConnection.disconnect();
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
if (out != null) {
|
|
320
|
+
out.close();
|
|
321
|
+
}
|
|
322
|
+
if (in != null) {
|
|
323
|
+
in.close();
|
|
324
|
+
}
|
|
325
|
+
} catch (final IOException e) {
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Workaround for bug pre-Froyo, see here for more info:
|
|
333
|
+
* http://android-developers.blogspot.com/2011/09/androids-http-clients.html
|
|
334
|
+
*/
|
|
335
|
+
public static void disableConnectionReuseIfNecessary() {
|
|
336
|
+
// HTTP connection reuse which was buggy pre-froyo
|
|
337
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) {
|
|
338
|
+
System.setProperty("http.keepAlive", "false");
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private static class ByteArrayOutputStreamInternal extends ByteArrayOutputStream {
|
|
343
|
+
public byte[] getBuffer() {
|
|
344
|
+
return buf;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Decode and sample down a bitmap from resources to the requested width and height.
|
|
350
|
+
*
|
|
351
|
+
* @param res The resources object containing the image data
|
|
352
|
+
* @param resId The resource id of the image data
|
|
353
|
+
* @param reqWidth The requested width of the resulting bitmap
|
|
354
|
+
* @param reqHeight The requested height of the resulting bitmap
|
|
355
|
+
* @param cache The Cache used to find candidate bitmaps for use with inBitmap
|
|
356
|
+
* @return A bitmap sampled down from the original with the same aspect ratio and dimensions
|
|
357
|
+
* that are equal to or greater than the requested width and height
|
|
358
|
+
*/
|
|
359
|
+
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight,
|
|
360
|
+
boolean keepAspectRatio, Cache cache) {
|
|
361
|
+
|
|
362
|
+
// BEGIN_INCLUDE (read_bitmap_dimensions)
|
|
363
|
+
// First decode with inJustDecodeBounds=true to check dimensions
|
|
364
|
+
final BitmapFactory.Options options = new BitmapFactory.Options();
|
|
365
|
+
options.inJustDecodeBounds = true;
|
|
366
|
+
BitmapFactory.decodeResource(res, resId, options);
|
|
367
|
+
|
|
368
|
+
options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight);
|
|
369
|
+
|
|
370
|
+
// END_INCLUDE (read_bitmap_dimensions)
|
|
371
|
+
|
|
372
|
+
// If we're running on Honeycomb or newer, try to use inBitmap
|
|
373
|
+
if (Utils.hasHoneycomb()) {
|
|
374
|
+
addInBitmapOptions(options, cache);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Decode bitmap with inSampleSize set
|
|
378
|
+
options.inJustDecodeBounds = false;
|
|
379
|
+
Bitmap bitmap = null;
|
|
380
|
+
InputStream is = null;
|
|
381
|
+
|
|
382
|
+
try {
|
|
383
|
+
final TypedValue value = new TypedValue();
|
|
384
|
+
is = res.openRawResource(resId, value);
|
|
385
|
+
bitmap = BitmapFactory.decodeResourceStream(res, value, is, null, options);
|
|
386
|
+
} catch (Exception e) {
|
|
387
|
+
/* do nothing.
|
|
388
|
+
If the exception happened on open, bm will be null.
|
|
389
|
+
If it happened on close, bm is still valid.
|
|
390
|
+
*/
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
if (bitmap == null) {
|
|
395
|
+
// throw new IllegalArgumentException("Problem decoding into existing bitmap");
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
ExifInterface ei = getExifInterface(is);
|
|
400
|
+
|
|
401
|
+
return scaleAndRotateBitmap(bitmap, ei, reqWidth, reqHeight, keepAspectRatio);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
@TargetApi(Build.VERSION_CODES.N)
|
|
405
|
+
private static ExifInterface getExifInterface(InputStream is) {
|
|
406
|
+
ExifInterface ei = null;
|
|
407
|
+
try {
|
|
408
|
+
if (Utils.hasN()) {
|
|
409
|
+
ei = new ExifInterface(is);
|
|
410
|
+
}
|
|
411
|
+
} catch (final Exception e) {
|
|
412
|
+
Log.e(TAG, "Error in reading bitmap - " + e);
|
|
413
|
+
} finally {
|
|
414
|
+
if (is != null) {
|
|
415
|
+
try {
|
|
416
|
+
is.close();
|
|
417
|
+
} catch (IOException e) {
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return ei;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
@TargetApi(Build.VERSION_CODES.N)
|
|
426
|
+
private static ExifInterface getExifInterface(FileDescriptor fd) {
|
|
427
|
+
ExifInterface ei = null;
|
|
428
|
+
try {
|
|
429
|
+
if (Utils.hasN()) {
|
|
430
|
+
ei = new ExifInterface(fd);
|
|
431
|
+
}
|
|
432
|
+
} catch (final Exception e) {
|
|
433
|
+
Log.e(TAG, "Error in reading bitmap - " + e);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return ei;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
private static ExifInterface getExifInterface(String fileName) {
|
|
440
|
+
ExifInterface ei = null;
|
|
441
|
+
try {
|
|
442
|
+
ei = new ExifInterface(fileName);
|
|
443
|
+
} catch (final Exception e) {
|
|
444
|
+
Log.e(TAG, "Error in reading bitmap - " + e);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return ei;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Decode and sample down a bitmap from a file to the requested width and height.
|
|
452
|
+
*
|
|
453
|
+
* @param fileName The full path of the file to decode
|
|
454
|
+
* @param reqWidth The requested width of the resulting bitmap
|
|
455
|
+
* @param reqHeight The requested height of the resulting bitmap
|
|
456
|
+
* @param cache The Cache used to find candidate bitmaps for use with inBitmap
|
|
457
|
+
* @return A bitmap sampled down from the original with the same aspect ratio and dimensions
|
|
458
|
+
* that are equal to or greater than the requested width and height
|
|
459
|
+
*/
|
|
460
|
+
public static Bitmap decodeSampledBitmapFromFile(String fileName, int reqWidth, int reqHeight,
|
|
461
|
+
boolean keepAspectRatio, Cache cache) {
|
|
462
|
+
|
|
463
|
+
// First decode with inJustDecodeBounds=true to check dimensions
|
|
464
|
+
final BitmapFactory.Options options = new BitmapFactory.Options();
|
|
465
|
+
options.inJustDecodeBounds = true;
|
|
466
|
+
BitmapFactory.decodeFile(fileName, options);
|
|
467
|
+
|
|
468
|
+
options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight);
|
|
469
|
+
|
|
470
|
+
// If we're running on Honeycomb or newer, try to use inBitmap
|
|
471
|
+
if (Utils.hasHoneycomb()) {
|
|
472
|
+
addInBitmapOptions(options, cache);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Decode bitmap with inSampleSize set
|
|
476
|
+
options.inJustDecodeBounds = false;
|
|
477
|
+
|
|
478
|
+
final Bitmap bitmap = BitmapFactory.decodeFile(fileName, options);
|
|
479
|
+
ExifInterface ei = getExifInterface(fileName);
|
|
480
|
+
|
|
481
|
+
return scaleAndRotateBitmap(bitmap, ei, reqWidth, reqHeight, keepAspectRatio);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
private static void closePfd(ParcelFileDescriptor pfd) {
|
|
485
|
+
if (pfd != null) {
|
|
486
|
+
try {
|
|
487
|
+
pfd.close();
|
|
488
|
+
} catch (IOException ignored) {
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Decode and sample down a bitmap from a file to the requested width and height.
|
|
495
|
+
*
|
|
496
|
+
* @param content The content uri of the file to decode
|
|
497
|
+
* @param reqWidth The requested width of the resulting bitmap
|
|
498
|
+
* @param reqHeight The requested height of the resulting bitmap
|
|
499
|
+
* @param cache The Cache used to find candidate bitmaps for use with inBitmap
|
|
500
|
+
* @return A bitmap sampled down from the original with the same aspect ratio and dimensions
|
|
501
|
+
* that are equal to or greater than the requested width and height
|
|
502
|
+
*/
|
|
503
|
+
public static Bitmap decodeSampledBitmapFromContent(String content, ContentResolver resolver, int reqWidth, int reqHeight,
|
|
504
|
+
boolean keepAspectRatio, Cache cache) {
|
|
505
|
+
|
|
506
|
+
// First decode with inJustDecodeBounds=true to check dimensions
|
|
507
|
+
final BitmapFactory.Options options = new BitmapFactory.Options();
|
|
508
|
+
options.inJustDecodeBounds = true;
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
Uri uri = android.net.Uri.parse(content);
|
|
512
|
+
ParcelFileDescriptor pfd = null;
|
|
513
|
+
try {
|
|
514
|
+
pfd = resolver.openFileDescriptor(uri, "r");
|
|
515
|
+
BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor(), null, options);
|
|
516
|
+
} catch (FileNotFoundException e) {
|
|
517
|
+
Log.v(TAG, "File not found " + content);
|
|
518
|
+
closePfd(pfd);
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight);
|
|
524
|
+
|
|
525
|
+
// If we're running on Honeycomb or newer, try to use inBitmap
|
|
526
|
+
if (Utils.hasHoneycomb()) {
|
|
527
|
+
addInBitmapOptions(options, cache);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Decode bitmap with inSampleSize set
|
|
531
|
+
options.inJustDecodeBounds = false;
|
|
532
|
+
|
|
533
|
+
final Bitmap bitmap = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor(), null, options);
|
|
534
|
+
|
|
535
|
+
ExifInterface ei = getExifInterface(pfd.getFileDescriptor());
|
|
536
|
+
closePfd(pfd);
|
|
537
|
+
|
|
538
|
+
return scaleAndRotateBitmap(bitmap, ei, reqWidth, reqHeight, keepAspectRatio);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
private static Bitmap scaleAndRotateBitmap(Bitmap bitmap, ExifInterface ei, int reqWidth, int reqHeight,
|
|
542
|
+
boolean keepAspectRatio) {
|
|
543
|
+
if (bitmap == null) {
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
int sourceWidth = bitmap.getWidth();
|
|
548
|
+
int sourceHeight = bitmap.getHeight();
|
|
549
|
+
|
|
550
|
+
reqWidth = reqWidth > 0 ? reqWidth : Math.min(sourceWidth, mDeviceWidthPixels);
|
|
551
|
+
reqHeight = reqHeight > 0 ? reqHeight : Math.min(sourceHeight, mDeviceHeightPixels);
|
|
552
|
+
|
|
553
|
+
// scale
|
|
554
|
+
if (reqWidth != sourceWidth || reqHeight != sourceHeight) {
|
|
555
|
+
boolean needsResize;
|
|
556
|
+
|
|
557
|
+
if (keepAspectRatio) {
|
|
558
|
+
double widthCoef = (double) sourceWidth / (double) reqWidth;
|
|
559
|
+
double heightCoef = (double) sourceHeight / (double) reqHeight;
|
|
560
|
+
double aspectCoef = Math.min(widthCoef, heightCoef);
|
|
561
|
+
|
|
562
|
+
reqWidth = (int) Math.floor(sourceWidth / aspectCoef);
|
|
563
|
+
reqHeight = (int) Math.floor(sourceHeight / aspectCoef);
|
|
564
|
+
|
|
565
|
+
// Update resize flag as values might revert back to original
|
|
566
|
+
needsResize = reqWidth != sourceWidth || reqHeight != sourceHeight;
|
|
567
|
+
} else {
|
|
568
|
+
needsResize = true;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// After preserving aspect ratio, check if bitmap still needs scaling
|
|
572
|
+
if (needsResize) {
|
|
573
|
+
bitmap = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// rotate
|
|
578
|
+
if (ei != null) {
|
|
579
|
+
final Matrix matrix = new Matrix();
|
|
580
|
+
final int rotationAngle = calculateRotationAngle(ei);
|
|
581
|
+
if (rotationAngle != 0) {
|
|
582
|
+
matrix.postRotate(rotationAngle);
|
|
583
|
+
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return bitmap;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
private static int calculateRotationAngle(ExifInterface ei) {
|
|
591
|
+
int rotationAngle = 0;
|
|
592
|
+
final int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
|
593
|
+
|
|
594
|
+
switch (orientation) {
|
|
595
|
+
case ExifInterface.ORIENTATION_ROTATE_90:
|
|
596
|
+
rotationAngle = 90;
|
|
597
|
+
break;
|
|
598
|
+
case ExifInterface.ORIENTATION_ROTATE_180:
|
|
599
|
+
rotationAngle = 180;
|
|
600
|
+
break;
|
|
601
|
+
case ExifInterface.ORIENTATION_ROTATE_270:
|
|
602
|
+
rotationAngle = 270;
|
|
603
|
+
break;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
return rotationAngle;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Decode and sample down a bitmap from a file input stream to the requested width and height.
|
|
611
|
+
*
|
|
612
|
+
* @param fileDescriptor The file descriptor to read from
|
|
613
|
+
* @param reqWidth The requested width of the resulting bitmap
|
|
614
|
+
* @param reqHeight The requested height of the resulting bitmap
|
|
615
|
+
* @param cache The Cache used to find candidate bitmaps for use with inBitmap
|
|
616
|
+
* @return A bitmap sampled down from the original with the same aspect ratio and dimensions
|
|
617
|
+
* that are equal to or greater than the requested width and height
|
|
618
|
+
*/
|
|
619
|
+
public static Bitmap decodeSampledBitmapFromDescriptor(FileDescriptor fileDescriptor, int reqWidth, int reqHeight,
|
|
620
|
+
boolean keepAspectRatio, Cache cache) {
|
|
621
|
+
|
|
622
|
+
// First decode with inJustDecodeBounds=true to check dimensions
|
|
623
|
+
final BitmapFactory.Options options = new BitmapFactory.Options();
|
|
624
|
+
options.inJustDecodeBounds = true;
|
|
625
|
+
BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
|
|
626
|
+
|
|
627
|
+
options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight);
|
|
628
|
+
|
|
629
|
+
// Decode bitmap with inSampleSize set
|
|
630
|
+
options.inJustDecodeBounds = false;
|
|
631
|
+
|
|
632
|
+
// If we're running on Honeycomb or newer, try to use inBitmap
|
|
633
|
+
if (Utils.hasHoneycomb()) {
|
|
634
|
+
addInBitmapOptions(options, cache);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
Bitmap results = null;
|
|
638
|
+
try {
|
|
639
|
+
// This can throw an error on a corrupted image when using an inBitmap
|
|
640
|
+
results = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
|
|
641
|
+
} catch (Exception e) {
|
|
642
|
+
// clear the inBitmap and try again
|
|
643
|
+
options.inBitmap = null;
|
|
644
|
+
results = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
|
|
645
|
+
// If image is broken, rather than an issue with the inBitmap, we will get a NULL out in this case...
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
ExifInterface ei = getExifInterface(fileDescriptor);
|
|
649
|
+
|
|
650
|
+
return scaleAndRotateBitmap(results, ei, reqWidth, reqHeight, keepAspectRatio);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
public static Bitmap decodeSampledBitmapFromByteArray(byte[] buffer, int reqWidth, int reqHeight,
|
|
654
|
+
boolean keepAspectRatio, Cache cache) {
|
|
655
|
+
|
|
656
|
+
// First decode with inJustDecodeBounds=true to check dimensions
|
|
657
|
+
final BitmapFactory.Options options = new BitmapFactory.Options();
|
|
658
|
+
options.inJustDecodeBounds = true;
|
|
659
|
+
BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options);
|
|
660
|
+
|
|
661
|
+
options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight);
|
|
662
|
+
|
|
663
|
+
// Decode bitmap with inSampleSize set
|
|
664
|
+
options.inJustDecodeBounds = false;
|
|
665
|
+
|
|
666
|
+
// If we're running on Honeycomb or newer, try to use inBitmap
|
|
667
|
+
if (Utils.hasHoneycomb()) {
|
|
668
|
+
addInBitmapOptions(options, cache);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
final Bitmap bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options);
|
|
672
|
+
|
|
673
|
+
InputStream is = new ByteArrayInputStream(buffer);
|
|
674
|
+
ExifInterface ei = getExifInterface(is);
|
|
675
|
+
|
|
676
|
+
return scaleAndRotateBitmap(bitmap, ei, reqWidth, reqHeight, keepAspectRatio);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding
|
|
681
|
+
* bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates
|
|
682
|
+
* the closest inSampleSize that is a power of 2 and will result in the final decoded bitmap
|
|
683
|
+
* having a width and height equal to or larger than the requested width and height.
|
|
684
|
+
*
|
|
685
|
+
* @param imageWidth The original width of the resulting bitmap
|
|
686
|
+
* @param imageHeight The original height of the resulting bitmap
|
|
687
|
+
* @param reqWidth The requested width of the resulting bitmap
|
|
688
|
+
* @param reqHeight The requested height of the resulting bitmap
|
|
689
|
+
* @return The value to be used for inSampleSize
|
|
690
|
+
*/
|
|
691
|
+
public static int calculateInSampleSize(int imageWidth, int imageHeight, int reqWidth, int reqHeight) {
|
|
692
|
+
// BEGIN_INCLUDE (calculate_sample_size)
|
|
693
|
+
// Raw height and width of image
|
|
694
|
+
final int height = imageHeight;
|
|
695
|
+
final int width = imageWidth;
|
|
696
|
+
reqWidth = reqWidth > 0 ? reqWidth : width;
|
|
697
|
+
reqHeight = reqHeight > 0 ? reqHeight : height;
|
|
698
|
+
int inSampleSize = 1;
|
|
699
|
+
if (height > reqHeight || width > reqWidth) {
|
|
700
|
+
|
|
701
|
+
final int halfHeight = height / 2;
|
|
702
|
+
final int halfWidth = width / 2;
|
|
703
|
+
|
|
704
|
+
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
|
|
705
|
+
// height and width larger than the requested height and width.
|
|
706
|
+
while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
|
|
707
|
+
inSampleSize *= 2;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// This offers some additional logic in case the image has a strange
|
|
711
|
+
// aspect ratio. For example, a panorama may have a much larger
|
|
712
|
+
// width than height. In these cases the total pixels might still
|
|
713
|
+
// end up being too large to fit comfortably in memory, so we should
|
|
714
|
+
// be more aggressive with sample down the image (=larger inSampleSize).
|
|
715
|
+
|
|
716
|
+
long totalPixels = (width / inSampleSize) * (height / inSampleSize);
|
|
717
|
+
|
|
718
|
+
// Anything more than 2x the requested pixels we'll sample down further
|
|
719
|
+
final long totalReqPixelsCap = reqWidth * reqHeight * 2;
|
|
720
|
+
|
|
721
|
+
while (totalPixels > totalReqPixelsCap) {
|
|
722
|
+
inSampleSize *= 2;
|
|
723
|
+
totalPixels = (width / inSampleSize) * (height / inSampleSize);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return inSampleSize;
|
|
727
|
+
// END_INCLUDE (calculate_sample_size)
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
|
731
|
+
private static void addInBitmapOptions(BitmapFactory.Options options, Cache cache) {
|
|
732
|
+
//BEGIN_INCLUDE(add_bitmap_options)
|
|
733
|
+
// inBitmap only works with mutable bitmaps so force the decoder to
|
|
734
|
+
// return mutable bitmaps.
|
|
735
|
+
options.inMutable = true;
|
|
736
|
+
|
|
737
|
+
if (cache != null) {
|
|
738
|
+
// Try and find a bitmap to use for inBitmap
|
|
739
|
+
Bitmap inBitmap = cache.getBitmapFromReusableSet(options);
|
|
740
|
+
|
|
741
|
+
if (inBitmap != null) {
|
|
742
|
+
options.inBitmap = inBitmap;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
//END_INCLUDE(add_bitmap_options)
|
|
746
|
+
}
|
|
747
|
+
}
|