mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-07 05:53:06 +00:00
fixed memory issue by reducing image size
This commit is contained in:
parent
cf6b974161
commit
3065a9a78c
5 changed files with 114 additions and 61 deletions
|
|
@ -167,10 +167,44 @@
|
|||
}
|
||||
}
|
||||
|
||||
+ (UIImage *)resizeImage:(UIImage *)image
|
||||
{
|
||||
float actualHeight = image.size.height;
|
||||
float actualWidth = image.size.width;
|
||||
float maxHeight = 200.0;
|
||||
float maxWidth = 200.0;
|
||||
float imgRatio = actualWidth/actualHeight;
|
||||
float maxRatio = maxWidth/maxHeight;
|
||||
float compressionQuality = 1;
|
||||
if (actualHeight > maxHeight || actualWidth > maxWidth)
|
||||
{
|
||||
if(imgRatio < maxRatio) {
|
||||
imgRatio = maxHeight / actualHeight;
|
||||
actualWidth = imgRatio * actualWidth;
|
||||
actualHeight = maxHeight;
|
||||
} else if(imgRatio > maxRatio) {
|
||||
imgRatio = maxWidth / actualWidth;
|
||||
actualHeight = imgRatio * actualHeight;
|
||||
actualWidth = maxWidth;
|
||||
} else {
|
||||
actualHeight = maxHeight;
|
||||
actualWidth = maxWidth;
|
||||
}
|
||||
}
|
||||
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
|
||||
UIGraphicsBeginImageContext(rect.size);
|
||||
[image drawInRect:rect];
|
||||
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
|
||||
NSData *imageData = UIImageJPEGRepresentation(img, compressionQuality);
|
||||
UIGraphicsEndImageContext();
|
||||
return [UIImage imageWithData:imageData];
|
||||
}
|
||||
|
||||
+ (void) saveDataToUserDefaults {
|
||||
const bctbx_list_t *logs = linphone_core_get_call_logs(LC);
|
||||
NSUserDefaults *mySharedDefaults = [[NSUserDefaults alloc] initWithSuiteName: @"group.belledonne-communications.linphone.widget"];
|
||||
NSMutableDictionary *dictShare = [NSMutableDictionary dictionary];
|
||||
NSMutableDictionary *images = [NSMutableDictionary dictionary];
|
||||
while (logs != NULL) {
|
||||
LinphoneCallLog *log = (LinphoneCallLog *)logs->data;
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
|
||||
|
|
@ -178,6 +212,15 @@
|
|||
logs = bctbx_list_next(logs);
|
||||
continue;
|
||||
}
|
||||
//FastAddressBook *fab = [LinphoneManager instance].fastAddressBook;
|
||||
Contact * contact = [FastAddressBook getContactWithAddress:linphone_call_log_get_remote_address(log)];
|
||||
if (contact && contact.avatar) {
|
||||
UIImage *image = [self resizeImage:contact.avatar];
|
||||
NSData *imageData = UIImageJPEGRepresentation(image, 0);
|
||||
[images setObject:imageData
|
||||
forKey:[[NSString stringWithUTF8String:linphone_address_as_string_uri_only(linphone_call_log_get_remote_address(log))] substringFromIndex:4]];
|
||||
NSLog(@"bjr%@", [[NSString stringWithUTF8String:linphone_address_as_string_uri_only(linphone_call_log_get_remote_address(log))] substringFromIndex:4]);
|
||||
}
|
||||
[dict setObject:[NSString stringWithUTF8String:linphone_call_log_get_call_id(log)]
|
||||
forKey:@"id"];
|
||||
[dict setObject:[NSString stringWithUTF8String:linphone_address_as_string(linphone_call_log_get_remote_address(log))]
|
||||
|
|
@ -192,6 +235,7 @@
|
|||
logs = bctbx_list_next(logs);
|
||||
}
|
||||
[mySharedDefaults setObject:dictShare forKey:@"logs"];
|
||||
[mySharedDefaults setObject:images forKey:@"imageData"];
|
||||
}
|
||||
|
||||
- (void)computeSections {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@
|
|||
}
|
||||
}
|
||||
[LinphoneManager.instance.iapManager check];
|
||||
[HistoryListTableView saveDataToUserDefaults];
|
||||
}
|
||||
|
||||
#pragma deploymate push "ignored-api-availability"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="acy-Dv-HTU">
|
||||
<rect key="frame" x="16" y="-25" width="288" height="87.5"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleAspectFit" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="ndj-Mq-Hl7">
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="ndj-Mq-Hl7">
|
||||
<rect key="frame" x="0.0" y="0.0" width="60" height="87.5"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wm5-Qb-p3S">
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
<constraint firstItem="ZCh-k6-wlC" firstAttribute="centerX" secondItem="ndj-Mq-Hl7" secondAttribute="centerX" id="7gN-E9-QSN"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleAspectFit" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="aDd-1O-GG5">
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="aDd-1O-GG5">
|
||||
<rect key="frame" x="76" y="0.0" width="60" height="87.5"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="YV6-7A-P4J">
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
<constraint firstItem="vzp-zG-86G" firstAttribute="centerX" secondItem="aDd-1O-GG5" secondAttribute="centerX" id="Reb-Z7-yZx"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleAspectFit" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Jda-ED-Hck">
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Jda-ED-Hck">
|
||||
<rect key="frame" x="152" y="0.0" width="60" height="87.5"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="R1m-4P-62J">
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
<constraint firstItem="1km-2d-H8g" firstAttribute="centerX" secondItem="Jda-ED-Hck" secondAttribute="centerX" id="Jaw-30-wJW"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleAspectFit" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Vem-dd-m97">
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Vem-dd-m97">
|
||||
<rect key="frame" x="228" y="0.0" width="60" height="87.5"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EgK-EE-9vt">
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
@property (strong, nonatomic) NSMutableDictionary *imgs;
|
||||
@property (strong, nonatomic) NSMutableArray *sortedDates;
|
||||
@property (strong, nonatomic) NSMutableArray *logIds;
|
||||
@property (strong) dispatch_semaphore_t sem;
|
||||
@property (nonatomic) BOOL updateNeeded;
|
||||
|
||||
- (IBAction)firstButtonTapped;
|
||||
- (IBAction)secondButtonTapped;
|
||||
|
|
|
|||
|
|
@ -24,68 +24,62 @@
|
|||
|
||||
NSUserDefaults *mySharedDefaults = [[NSUserDefaults alloc] initWithSuiteName: @"group.belledonne-communications.linphone.widget"];
|
||||
NSMutableArray *dates = [NSMutableArray array];
|
||||
[_imgs removeAllObjects];
|
||||
_imgs = nil;
|
||||
_imgs = [NSMutableDictionary dictionaryWithDictionary:[mySharedDefaults objectForKey:@"imageData"]];
|
||||
NSDictionary *logsTmp = [mySharedDefaults objectForKey:@"logs"];
|
||||
_logs = [NSMutableDictionary dictionary];
|
||||
[_logs removeAllObjects];
|
||||
for (NSString *dateStr in logsTmp.allKeys) {
|
||||
NSDictionary *log = [logsTmp objectForKey:dateStr];
|
||||
NSDate *date = [formatter dateFromString:dateStr];
|
||||
[dates addObject:date];
|
||||
[_logs setObject:log forKey:date];
|
||||
}
|
||||
[_sortedDates removeAllObjects];
|
||||
_sortedDates = nil;
|
||||
_sortedDates = [[NSMutableArray alloc]
|
||||
initWithArray:[dates sortedArrayUsingComparator:^NSComparisonResult(NSDate *d1, NSDate *d2) {
|
||||
return [d2 compare:d1]; // reverse order
|
||||
}]];
|
||||
}
|
||||
|
||||
- (void) fetchContactsInBackGroundThread{
|
||||
_imgs = [NSMutableDictionary dictionary];
|
||||
CNContactStore *store = [[CNContactStore alloc] init];
|
||||
CNEntityType entityType = CNEntityTypeContacts;
|
||||
[store requestAccessForEntityType:entityType completionHandler:^(BOOL granted, NSError *_Nullable error) {
|
||||
BOOL success = FALSE;
|
||||
if(granted){
|
||||
//LOGD(@"CNContactStore authorization granted");
|
||||
|
||||
NSError *contactError;
|
||||
CNContactStore* store = [[CNContactStore alloc] init];
|
||||
[store containersMatchingPredicate:[CNContainer predicateForContainersWithIdentifiers:@[ store.defaultContainerIdentifier]] error:&contactError];
|
||||
NSArray *keysToFetch = @[
|
||||
CNContactImageDataAvailableKey, CNContactInstantMessageAddressesKey,
|
||||
CNContactIdentifierKey, CNContactImageDataKey
|
||||
];
|
||||
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keysToFetch];
|
||||
|
||||
success = [store enumerateContactsWithFetchRequest:request error:&contactError usingBlock:^(CNContact *__nonnull contact, BOOL *__nonnull stop) {
|
||||
if (contactError) {
|
||||
NSLog(@"error fetching contacts %@",
|
||||
contactError);
|
||||
} else {
|
||||
if (contact.imageDataAvailable) {
|
||||
NSArray *addresses = contact.instantMessageAddresses;
|
||||
NSString *address = @"";
|
||||
for (CNLabeledValue *v in addresses) {
|
||||
CNInstantMessageAddress *addressValue = v.value;
|
||||
if ([addressValue.service isEqualToString:@"SIP"]) {
|
||||
address = addressValue.username;
|
||||
[self.imgs setObject:contact.imageData
|
||||
forKey:address];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
dispatch_semaphore_signal(self.sem);
|
||||
- (UIImage *)resizeImage:(UIImage *)image
|
||||
{
|
||||
float actualHeight = image.size.height;
|
||||
float actualWidth = image.size.width;
|
||||
float maxHeight = 200.0;
|
||||
float maxWidth = 200.0;
|
||||
float imgRatio = actualWidth/actualHeight;
|
||||
float maxRatio = maxWidth/maxHeight;
|
||||
float compressionQuality = 1;
|
||||
if (actualHeight > maxHeight || actualWidth > maxWidth)
|
||||
{
|
||||
if(imgRatio < maxRatio) {
|
||||
imgRatio = maxHeight / actualHeight;
|
||||
actualWidth = imgRatio * actualWidth;
|
||||
actualHeight = maxHeight;
|
||||
} else if(imgRatio > maxRatio) {
|
||||
imgRatio = maxWidth / actualWidth;
|
||||
actualHeight = imgRatio * actualHeight;
|
||||
actualWidth = maxWidth;
|
||||
} else {
|
||||
actualHeight = maxHeight;
|
||||
actualWidth = maxWidth;
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
|
||||
UIGraphicsBeginImageContext(rect.size);
|
||||
[image drawInRect:rect];
|
||||
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
|
||||
NSData *imageData = UIImageJPEGRepresentation(img, compressionQuality);
|
||||
UIGraphicsEndImageContext();
|
||||
return [UIImage imageWithData:imageData];
|
||||
}
|
||||
|
||||
- (void)draw {
|
||||
_contactsToDisplay = [NSMutableArray array];
|
||||
_logIds = [NSMutableArray array];
|
||||
[_contactsToDisplay removeAllObjects];
|
||||
[_logIds removeAllObjects];
|
||||
int i = 0, j = 0;
|
||||
dispatch_semaphore_wait(_sem, DISPATCH_TIME_FOREVER);
|
||||
while (i < _stackViews.count && j < _sortedDates.count) {
|
||||
NSDate *date = _sortedDates[j++];
|
||||
NSString *address = [[_logs objectForKey:date] objectForKey:@"address"];
|
||||
|
|
@ -96,16 +90,18 @@
|
|||
continue;
|
||||
[_contactsToDisplay addObject:address];
|
||||
[_logIds addObject:logId];
|
||||
NSString *displayName = [NSString stringWithUTF8String:linphone_address_get_display_name(adr)];
|
||||
NSString *displayName = [NSString stringWithUTF8String:(linphone_address_get_display_name(adr))?:linphone_address_get_username(adr)];
|
||||
UIStackView *stack = _stackViews[i];
|
||||
UIButton *button = stack.subviews[0];
|
||||
// making rounded image
|
||||
UIImageView *imageView = button.imageView;
|
||||
imageView.layer.cornerRadius = imageView.frame.size.height / 2;
|
||||
imageView.clipsToBounds = YES;
|
||||
UILabel *name = stack.subviews[1];
|
||||
if ([self.imgs.allKeys containsObject:address])
|
||||
[button setImage:[UIImage imageWithData:[_imgs objectForKey:address]] forState:UIControlStateNormal];
|
||||
if ([self.imgs.allKeys containsObject:address]) {
|
||||
NSData *imgData = [_imgs objectForKey:address];
|
||||
// UIImage *image = [UIImage imageWithData:imgData];
|
||||
// image = [self resizeImage:image];
|
||||
// NSData *data = UIImageJPEGRepresentation(image, 0);
|
||||
[button setImage:[UIImage imageWithData:imgData] forState:UIControlStateNormal];
|
||||
NSLog(@"Size of Image(bytes):%d", (int)[imgData length]);
|
||||
}
|
||||
[stack setAlpha:1];
|
||||
button.enabled = YES;
|
||||
[name setText:displayName];
|
||||
|
|
@ -123,15 +119,28 @@
|
|||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view from its nib.
|
||||
_sem = dispatch_semaphore_create(0);
|
||||
[self fetchContactsInBackGroundThread];
|
||||
[self loadData];
|
||||
[self draw];
|
||||
for (UIStackView *stack in _stackViews) {
|
||||
UIButton *button = stack.subviews[0];
|
||||
// making rounded image
|
||||
UIImageView *imageView = button.imageView;
|
||||
imageView.layer.cornerRadius = imageView.frame.size.height / 2;
|
||||
imageView.clipsToBounds = YES;
|
||||
}
|
||||
_logIds = [NSMutableArray array];
|
||||
_logs = [NSMutableDictionary dictionary];
|
||||
_sortedDates = [NSMutableArray array];
|
||||
_contactsToDisplay = [NSMutableArray array];
|
||||
_imgs = [NSMutableDictionary dictionary];
|
||||
_updateNeeded = YES;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
[_imgs removeAllObjects];
|
||||
[_logs removeAllObjects];
|
||||
[_sortedDates removeAllObjects];
|
||||
[_contactsToDisplay removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
|
||||
|
|
@ -140,7 +149,6 @@
|
|||
// If an error is encountered, use NCUpdateResultFailed
|
||||
// If there's no update required, use NCUpdateResultNoData
|
||||
// If there's an update, use NCUpdateResultNewData
|
||||
[self fetchContactsInBackGroundThread];
|
||||
[self loadData];
|
||||
[self draw];
|
||||
completionHandler(NCUpdateResultNewData);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue