B4i Library iQBImagePicker - Multiple selection image picker

This is a wrapper for QBImagePicker https://github.com/questbeat/QBImagePicker, an image picker that provides for multiple image and video selection.

The wrapper includes helper functions which are primarily to copy the selected assets to a folder on the device but a few others have been included since I required them.

I have noticed that on the Simulator only local (in the DCIM folder) assets can be copied (not sure why) but on a real device I haven't noticed that limitation.

The list of PHAssetCollectionSubtypes (one or more of which are passed to the load function) can be found here https://github.com/mstg/iOS-full-sd...eworks/Photos.framework/Headers/PhotosTypes.h

QBImagePicker has built-in support for the following languages: English, French, German, Spanish, Italian, Korean, Japanese, Chinese Taiwan, Simplified Chinese, Portuguese, Polish, Russian.

Installation instructions (modified one of Alberto Iglesias' posts since I haven't tried the MAC HOSTED approach):

- Unzip QBImagePicker.zip into the folder "Libs" in your MAC or in your MAC HOSTED by AnywhereSoftware, normally in "B4i-MacServer\Libs" folder. This will result in iQBImagePicker.h, libiQBImagePicker.a and the folder QBImagePicker.framework being copied to the "Libs" folder.

-Copy the iQBImagePicker.xml to your custom libraries folder in B4i

-If you wish to use the simulator then use QBImagePickerSim.zip instead of QBImagePicker.zip. (There are only two files that are different between the two zips: libiQBImagePicker.a and QBImagePicker.framework/QBImagePicker.)

22/01/21 - Updated the demo and XML file to remove the references to passing -1 as a subType since it doesn't work.

08/05/21 - ver 1.10
Added Russian language localisation.​

22/05/21 - ver 1.20
Added a call to add your own language translation.
If you wish to use QBImagePicker with a language that is not built-in to the framework, you can you the command QBImagePicker.translations to provide your own translations for the required 11 strings.​
Added a call to return the framework's version number: QBImagePicker.frameworkVersion​

For the non-English languages to be recognised, you need to create subfolders in your project's files/special folder as per this thread: https://www.b4x.com/android/forum/threads/tutorial-for-localization-of-app-name.69618

iQBImagePicker

Author: Capt Kronos
Version: 1.2
  • QBImagePicker
    • Events:
      • cancelled
      • picked (assets As List)
    • Functions:
      • convertPHAssetToImage (thePHAsset As PHAsset*) As UIImage*
        <code>dim bmp as bitmap = aQBImagePicker.ConvertPHAssetToImage(assets.Get(i))</code>
      • copyPHAssetToFile (ThePHAsset As PHAsset*, destination As NSString*)
        <code>aQBImagePicker.CopyPHAssetToFile(assets.Get(i), "filename")</code>
      • createAlbum (albumName As NSString*) As BOOL
        <code>aQBImagePicker.createAlbum("myalbum") 'if myalbum already exists another album of the same name will be created</code>
      • existsAlbum (albumName As NSString*) As BOOL
        <code>aQBImagePicker.existsAlbum("myalbum") 'returns true if myalbum exists</code>
      • frameworkVersion As NSString*
        Returns the version of the framework.
      • getImageDataFromAsset (thePHAsset As PHAsset*) As NSDictionary*
        Be very careful with this one. Depending on which key you inspect, it can crash your app.
        <code>Dim dict As Object, dictMap As Map
        dict=QBImagePicker.getImageDataFromAsset(assets.Get(0))
        dictMap=NSDictionaryToMap(dict)
        Log(dictMap.Get("PHImageFileUTIKey"))</code>
      • getImageURLFromAsset (thePHAsset As PHAsset*) As NSString*
        <code>Dim url As String=QBPicker.getImageURLFromAsset(assets.Get(i))
        url=url.SubString(7) 'convert to regular path and filename</code>
      • initialize (bi As B4I*, eventName As NSString*)
        Initialises the picker.
        Example:<code>aQBImagePicker.initialize("qbimagepicker")</code>
      • load (myViewController As UIViewController*, mediaType As Int, subType As NSArray*, multiSelect As BOOL, minNumber As Int, maxNumber As Int, numColsInPortrait As Int, numColsInLandscape As Int, useiCloud As BOOL)
        Displays the picker.
        MyViewController: The page to host the picker
        MediaType: 1 - images; 2 - videos; 0 - any
        SubType: a list of PHAssetCollectionSubtypes - see below for the values
        <code>github.com/mstg/iOS-full-sdk/blob/master/iPhoneOS9.3.sdk/System/Library/Frameworks/Photos.framework/Headers/PhotosTypes.h</code>
        MultiSelect: True - allows more than one asset to be selected
        MinNumber: The minimum number of assets that must be selected
        MaxNumber: The maximum number of assets that can be selected
        NumColsInPortrait: The number of assets to display horizontally when in portrait (0 for default value)
        NumColsInLandscape: The number of assets to display horizontally when in landscape (0 for default value)
        useiCloud: True - will display assets on iCloud
        Example:<code>
        aQBImagePicker.load(pg, 1, subType, True, 1, 100, 0, 0, True)</code>
      • saveImageFileToAlbum (albumName As NSString*, imageURL As NSString*) As BOOL
        <code>aQBImagePicker.saveImageFileToAlbum("myalbum", File.Combine(File.DirDocuments,"myimage.jpg"))</code>
      • saveImageToAlbum (albumName As NSString*, image As UIImage*) As BOOL
        <code>aQBImagePicker.saveImageToAlbum("myalbum", bmp)</code>
      • saveVideoFileToAlbum (albumName As NSString*, videoURL As NSString*) As BOOL
        <code>aQBImagePicker.saveVideoFileToAlbum("myalbum", File.Combine(File.DirDocuments,"myvideo.mp4"))</code>
      • translations (albumsTitle As NSString*, assetsToolbarItemsSelected As NSString*, assetsToolbarItemSelected As NSString*, assetsFooterPhotoAndVideo As NSString*, assetsFooterPhotoAndVideos As NSString*, assetsFooterPhotosAndVideo As NSString*, assetsFooterPhotosAndVideos As NSString*, assetsFooterPhoto As NSString*, assetsFooterPhotos As NSString*, assetsFooterVideos As NSString*, assetsFooterVideos As NSString*)
        Overrides built-in translations
        <code>aQBImagePicker.translations( _
        "Photos", _​
        "%ld Items Selected", _​
        "%ld Item Selected", _​
        "%ld Photo, %ld Video", _​
        "%ld Photo, %ld Videos", _​
        "%ld Photos, %ld Video", _​
        "%ld Photos, %ld Videos", _​
        "%ld Photo", _​
        "%ld Photos", _​
        "%ld Video", _​
        "%ld Videos")​
        </code>


Usage:
B4X:
Dim aQBImagePicker As QBImagePicker
Dim subType As List
subType.Initialize
subType.Add(201)
aQBImagePicker.initialize("QBImagePicker")
'optionally, add a translation (translate the English parameters to the required language)
aQBImagePicker.translations( _ 
	"Photos", _
	"%ld Items Selected", _
	"%ld Item Selected", _
	"%ld Photo, %ld Video", _
	"%ld Photo, %ld Videos", _
	"%ld Photos, %ld Video", _
	"%ld Photos, %ld Videos", _
	"%ld Photo", _
	"%ld Photos", _
	"%ld Video", _
	"%ld Videos")
aQBImagePicker.load(Page1,1,subType,True,0,10,0,0,True)

Sub QBImagePicker_picked (assets As List)
    For i=0 To assets.Size-1
        QBPicker.CopyPHAssetToFile(assets.Get(i), destFilname)
    Next
End Sub
 

Attachments

  • QBImagePickerDemo.zip
    2.8 KB · Views: 31
  • iQBImagePicker.xml
    10 KB · Views: 23
  • QBImagePicker.zip
    259.7 KB · Views: 25
  • QBImagePickerSim.zip
    372 KB · Views: 24
Last edited:

lymey

Active Member
Licensed User
Longtime User
Not sure why you are getting a nul url though I noticed you are trying to get a very large image. Perhaps try with a smaller one to start with?
It's a standard size picture taken with the onboard camera.
I am trying with different images and now getting this result on the break point:
1611249958514.png
 

lymey

Active Member
Licensed User
Longtime User
It would be nice to know why you are getting the nul URL but if you just need the filename and directory, the following (not tested) should work:

B4X:
Dim no As NativeObject=assets.Get(0)
Dim fn As String=no.GetField("_filename").AsString
Dim dir As String=no.GetField("_directory").AsString
Yes that works nicely!
 

lymey

Active Member
Licensed User
Longtime User
Not sure if device is important, I'm using an Iphone 7 with ios 14.0.1
 

CaptKronos

Active Member
Licensed User
Longtime User
Possibly. I only have an iPhone 6 with 12.4.9. I'll try with the simulator tomorrow.
Just tried with the simulator, which is running 14.3, and the URL is returned correctly. Perhaps you can work around this function not working for you? Is everything else working?
 

lymey

Active Member
Licensed User
Longtime User
I think I can work around it. I haven't had a chance to get back to it since last night, I wondered if it's a permissions thing. I'll start using it and keep you posted.
Thanks for the help!
 

CaptKronos

Active Member
Licensed User
Longtime User
I doubt it is a permission thing since if it was, you wouldn't be getting any assets returned.
I have updated the opening post just to remove references to passing a value of -1 as a subtype - since passing that value doesn't work. I doubt that has anything to do with the problem you are seeing but just for future reference, don't pass -1!
 

red30

Well-Known Member
Licensed User
Longtime User
Сan i add my own language somehow? My phone is in Russian, but when I press "Tap me" then all the inscriptions are in English.
 

CaptKronos

Active Member
Licensed User
Longtime User
If you have a look here https://github.com/questbeat/QBImagePicker/pull/197/commits/dea25ca3041eb3e733f146684be6012a24b695b0 you will find how Brazilian and Portuguese languages were added. If you want to send me the QBImagePicker.strings file translated into Russian, I'll have a go at building a new version of the framework. Though it might take me a while to do it (I'll need to find all the files again and I'm a bit busy at the moment) so if your need is urgent it might be best just to go with the English text.
 

red30

Well-Known Member
Licensed User
Longtime User
If you have a look here https://github.com/questbeat/QBImagePicker/pull/197/commits/dea25ca3041eb3e733f146684be6012a24b695b0 you will find how Brazilian and Portuguese languages were added. If you want to send me the QBImagePicker.strings file translated into Russian, I'll have a go at building a new version of the framework. Though it might take me a while to do it (I'll need to find all the files again and I'm a bit busy at the moment) so if your need is urgent it might be best just to go with the English text.
It will not be difficult for me to translate into Russian. I just don't quite understand what to translate?
B4X:
/*
  QBImagePicker.strings
  QBImagePicker

  Created by Katsuma Tanaka on 2015/04/03.
  Copyright (c) 2015 Katsuma Tanaka. All rights reserved.
*/

"albums.title" = "Photos";

"assets.footer.photo" = "%ld Photo";
"assets.footer.photos" = "%ld Photos";
"assets.footer.video" = "%ld Video";
"assets.footer.videos" = "%ld Videos";
"assets.footer.photo-and-video" = "%ld Photo, %ld Video";
"assets.footer.photos-and-video" = "%ld Photos, %ld Video";
"assets.footer.photo-and-videos" = "%ld Photo, %ld Videos";
"assets.footer.photos-and-videos" = "%ld Photos, %ld Videos";

"assets.toolbar.item-selected" = "%ld Item Selected";
"assets.toolbar.items-selected" = "%ld Items Selected";
There are only words "photo(s)", video(s) and "selected item(s)". But what about "cancel" and "done" in the English version?

B4X:
/*
  QBImagePicker.strings
  QBImagePicker

  Created by Katsuma Tanaka on 2015/04/03.
  Copyright (c) 2015 Katsuma Tanaka. All rights reserved.
*/

"albums.title" = "Фото";

"assets.footer.photo" = "%ld Фото";
"assets.footer.photos" = "%ld Фото";
"assets.footer.video" = "%ld Видео";
"assets.footer.videos" = "%ld Видео";
"assets.footer.photo-and-video" = "%ld Фото, %ld Видео";
"assets.footer.photos-and-video" = "%ld Фото, %ld Видео";
"assets.footer.photo-and-videos" = "%ld Фото, %ld Видео";
"assets.footer.photos-and-videos" = "%ld Фото, %ld Видео";

"assets.toolbar.item-selected" = "Элементов выбрано: %ld";
"assets.toolbar.items-selected" = "Элементов выбрано: %ld";
There is only a problem with "Item Selected". In English 1 Item Selected, 2,3,4 ... Items Selected.
In Russian, everything is more complicated:
1) If the number ends in 1 (except 11), then there will always be "Элемент выбран")
2) If the number ends in 2,3,4 (except 12,13,14), then "Элемента выбрано"
3) If the number ends with 0,5,6,7,8,9,11,12,13,14,15 then "Элементов выбрано"
If it was possible to change this phrase to "Elements selected: %ld", then in Russian it can be replaced with one phrase "Элементов выбрано: %ld". I changed the file for Russian language accordingly
 
Last edited:

CaptKronos

Active Member
Licensed User
Longtime User
It would appear that the author didn't provide the opportunity to add a translation for "cancel" and "done". I'll see how difficult it would be to hack one in. With regards "Item Selected", would it be possible just to go with the singular and plural options, and just put up with the grammatical errors? Any idea why Russian makes it so complicated?
 

red30

Well-Known Member
Licensed User
Longtime User
It would appear that the author didn't provide the opportunity to add a translation for "cancel" and "done". I'll see how difficult it would be to hack one in. With regards "Item Selected", would it be possible just to go with the singular and plural options, and just put up with the grammatical errors? Any idea why Russian makes it so complicated?
It turns out that "cancel" and "done " are not translated in all languages?
I think with "Item Selected" it is better to do as I wrote in the last version, where I changed the structure of the sentence: "Элементов выбрано: %ld"
As I also noticed the word "Recents", it is also not where it is, but it can also be translated.
 

CaptKronos

Active Member
Licensed User
Longtime User
Red30: I have updated the opening post with a framework that includes your Russian translations. I have also updated the instructions which explains how to get the localisations working.
 

red30

Well-Known Member
Licensed User
Longtime User
Red30: I have updated the opening post with a framework that includes your Russian translations. I have also updated the instructions which explains how to get the localisations working.
Many thanks!
I can't add Russian or I don't understand something. I have updated the "QBImagePicker.zip" and "iQBImagePicker.xml" files. Then I created the "ru.lproj" folder in \ Files \ Special and copied the "QBImagePickerDemo" file from the "ru-RU.lproj" folder there. I get the error "The given key was not present in the dictionary."
What am I doing wrong?
 

CaptKronos

Active Member
Licensed User
Longtime User
I think you have misunderstood the instructions. Within the ru.lproj folder you create a file with the name "InfoPlist.strings" and contents:
B4X:
"CFBundleDisplayName" = "My App";
"CFBundleName" = "My App";
You will also probably want to support the English language for your non-Russian users, so you will create another folder: en.lproj with its own copy of InfoPlist.strings.
 

red30

Well-Known Member
Licensed User
Longtime User
I think you have misunderstood the instructions. Within the ru.lproj folder you create a file with the name "InfoPlist.strings" and contents:
B4X:
"CFBundleDisplayName" = "My App";
"CFBundleName" = "My App";
You will also probably want to support the English language for your non-Russian users, so you will create another folder: en.lproj with its own copy of InfoPlist.strings.
Yes, now the standard words ("done", "cancel", "recent") have become in Russian, but "Photo", "Video" and "Selected items" are there in English ...
 

CaptKronos

Active Member
Licensed User
Longtime User
Are you using a local mac builder? If so, are you sure you have copied iQBImagePicker.h, libiQBImagePicker.a and the folder QBImagePicker.framework to your mac builder's "Libs" folder? It sounds like your app is using the previous version of QBImagePicker. If you are using the hosted builder, you will need to request Erel to install it on the hosted builder.
 

red30

Well-Known Member
Licensed User
Longtime User
Are you using a local mac builder? If so, are you sure you have copied iQBImagePicker.h, libiQBImagePicker.a and the folder QBImagePicker.framework to your mac builder's "Libs" folder? It sounds like your app is using the previous version of QBImagePicker. If you are using the hosted builder, you will need to request Erel to install it on the hosted builder.
I am using Hosted Mac Builder. I thought the new libraries were already added to the Hosted Mac Builder. Hopefully
Erel sees this post and added new libraries! Thank you!
 
Top