fixed memory issue by reducing image size

This commit is contained in:
David Idmansour 2018-06-15 17:06:49 +02:00
parent cf6b974161
commit 3065a9a78c
5 changed files with 114 additions and 61 deletions

View file

@ -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 {

View file

@ -138,6 +138,7 @@
}
}
[LinphoneManager.instance.iapManager check];
[HistoryListTableView saveDataToUserDefaults];
}
#pragma deploymate push "ignored-api-availability"

View file

@ -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">

View file

@ -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;

View file

@ -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);