I need to upload an Image to the sever, and have to request in the background in case of the user press the home button.
- (void)uploadImage
{
AppDelegate * app = (AppDelegate *)[UIApplication sharedApplication].delegate;
[app.uploadAndDownManager uploadIDImageWithImage:_im.image];
}
-(void)uploadIDImageWithImage:(UIImage *)image
{
if (!_uploadImage) {
_uploadImage = image;
}
[self uploadImageInBackground];
}
- (void)uploadImageInBackground
{
_uploadImageTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:_uploadImageTask];
_uploadImageTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task, preferably in chunks.
// your code
// NSLog(#" %f",[UIApplication sharedApplication].backgroundTimeRemaining);
[self test];
[[UIApplication sharedApplication] endBackgroundTask:_uploadImageTask];
_uploadImageTask = UIBackgroundTaskInvalid;
});
}
-(void)test
{
NSString * userStr = [[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
NSString * portNumber = [[NSUserDefaults standardUserDefaults] objectForKey:#"portNumber"];
NSString * urlStr = URL_ADDRESS(portNumber, #"uploadAction_execute.action");
NSURL * url = [NSURL URLWithString:urlStr];
NSData * data = UIImageJPEGRepresentation(_uploadImage, 0.8);
//保存本地
[self saveToLocalDocument:data];
ASIFormDataRequest * re = [ASIFormDataRequest requestWithURL:url];
re.delegate = self;
[re setData:data withFileName:[NSString stringWithFormat:#"%#_id_.jpg",userStr] andContentType:#"image/jpg" forKey:#"file"];
[re setRequestMethod:#"POST"];
[re setDidFinishSelector:#selector(finish:)];
[re setDidFailSelector:#selector(failed:)];
// [re startAsynchronous];
[re startSynchronous];
}
In case the request is failed, I let it request automatically:
- (void)failed:(ASIFormDataRequest *)request
{
NSLog(#"error %#",request.error);
[self performSelector:#selector(uploadIDImageWithImage:) withObject:nil afterDelay:REQUEST_AGAIN_TIME];
// [SVProgressHUD showImage:nil status:#"验证提交成功,等待审核"];
}
When I press the home button, it may works but it can be out of time sometimes. When it fails, it won't request again! If the request asynchronous, it won't work until I enter the foreground again.
How can I fix it?
I put the code
[[UIApplication sharedApplication] endBackgroundTask:_uploadImageTask];
_uploadImageTask = UIBackgroundTaskInvalid;
in the success method finish:, it seems worked:
If there are other methods or any problem in this way, please let me know, thanks!
Related
I am getting warning [UIApplication delegate] must be used from main thread only in the below line of code
((AppDelegate *)[[UIApplication sharedApplication]
delegate]).loginProfile.accessToken;
Following is my code.
+ (NSString *)accessTokenHashForDate:(NSDate *)date withParameters:(NSArray *)params{
NSString *accessToken = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).loginProfile.accessToken;
NSString *paramsStr = [params componentsJoinedByString:#""];
NSString *hashStr = [NSString stringWithFormat:#"%#%#%#%#", [CommonUtil IMEI], [date agileHashFormattedString], (!paramsStr) ? #"" : paramsStr, accessToken];
return hashStr
}
Can anyone tell me how to remove this warning message?
+ (NSString *)accessTokenHashForDate:(NSDate *)date withParameters:(NSArray *)params{
__block NSString *accessToken = NULL;
if ([NSThread isMainThread]) {
accessToken = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).loginProfile.accessToken;
} else {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_main_queue(), ^{
accessToken = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).loginProfile.accessToken;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(semaphore);
}
NSString *paramsStr = [params componentsJoinedByString:#""];
NSString *hashStr = [NSString stringWithFormat:#"%#%#%#%#", [CommonUtil IMEI], [date agileHashFormattedString], (!paramsStr) ? #"" : paramsStr, accessToken];
return hashStr;
}
I am new in iOS and I am facing problem regarding to check new update available to Apple Store.
Is there is any API to check?
do like
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Fabric implementation
[self needsUpdate:^(NSDictionary *dictionary) {
// you can use the dictionary here
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
if ([dictionary[#"resultCount"] integerValue] == 1){
NSString* appStoreVersion = dictionary[#"results"][0][#"version"];
NSString* currentVersion = infoDictionary[#"CFBundleShortVersionString"];
if (![appStoreVersion isEqualToString:currentVersion]){
NSLog(#"Need to update [%# != %#]", appStoreVersion, currentVersion);
[self showAlert];
}
}
// if you want to update UI or model, dispatch this to the main queue:
// dispatch_async(dispatch_get_main_queue(), {
// do your UI stuff here
// do nothing
// });
}];
}
for reference purpose I taken the answer from here
-(void)needsUpdate:(void (^)(NSDictionary * dictionary))completionHandler{
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString* appID = infoDictionary[#"CFBundleIdentifier"];
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:#"http://itunes.apple.com/lookup?bundleId=%#", appID]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if (completionHandler) {
completionHandler(lookup);
}
}];
[task resume];
}
show the alert
-(void)showAlert
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"please update app" message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:#"Okay!" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action)
{
#try
{
NSLog(#"tapped ok");
BOOL canOpenSettings = (UIApplicationOpenSettingsURLString != NULL);
if (canOpenSettings)
{
NSURL *url = [NSURL URLWithString:#"https://itunes.apple.com/in/app/tvfplay/id1067732674?mt=8"];
[[UIApplication sharedApplication] openURL:url options:#{} completionHandler:nil];
}
}
#catch (NSException *exception)
{
}
}]];
UIWindow* topWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
topWindow.rootViewController = [UIViewController new];
topWindow.windowLevel = UIWindowLevelAlert + 1;
[topWindow makeKeyAndVisible];
[topWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
}
There is no direct API available for app update checking but you can check current version to iTune version.
Please check below links for the same :
SO Answer's:
IOS app update check within application
Check if my app has a new version on AppStore
There is also one library for checking update :
https://github.com/nicklockwood/iVersion
Hope this will helps you to check your app update.
I am trying to correctly handle in-process NSURLSessionTasks in the event that the app enters the background (e.g from a home button press). I am currently taking the approach of copying the in-process tasks across to the background queue (see code below). I am finding however that the background tasks are behaving erratically and not always finishing. Can any spot what I might be doing wrong / advise on the best approach ?
- (void)appWillResignActive : (NSNotification *)notification {
UIApplication *app = [UIApplication sharedApplication];
// Register expiring background task
__block UIBackgroundTaskIdentifier bgTaskId =
[app beginBackgroundTaskWithExpirationHandler:^{
bgTaskId = UIBackgroundTaskInvalid;
}];
[self switchToBackground];
[app endBackgroundTask:bgTaskId];
}
- (void)appWillBecomeActive : (NSNotification *)notification {
[self switchToForeground];
}
- (void)switchToBackground
{
NSLog(#"Switch to background line 217 Network Manager");
if ([state isEqualToString: kdownloadManagerStateForeground]) {
[urlSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
[downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
NSURLSessionDownloadTask *downloadTask = [self.backgroundSession downloadTaskWithResumeData:resumeData];
[downloadTask resume];
}];
}
}];
state = kdownloadManagerStateBackground;
}
}
- (void)switchToForeground
{
if ([state isEqualToString: kdownloadManagerStateBackground]) {
[backgroundSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
[downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
NSURLSessionDownloadTask *downloadTask = [self.urlSession downloadTaskWithResumeData:resumeData];
[downloadTask resume];
}];
}
}];
state = kdownloadManagerStateForeground;
}
}
Background sessions let you perform uploads and downloads of content in the background while your app is not running. You can create a background session configuration by calling the backgroundSessionConfiguration: method on the NSURLSessionConfiguration class.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
NSURLSessionConfiguration *sessionConfig;
float timeout = 5 * 60.0f;
BOOL iOS8OrNew = [[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0;
if (iOS8OrNew) {
sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
request.timeoutInterval = timeout;
}
else {
sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
sessionConfig.timeoutIntervalForRequest = timeout;
}
sessionConfig.HTTPMaximumConnectionsPerHost = 10;
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:sessionConfig];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request];
[manager setDidFinishEventsForBackgroundURLSessionBlock:^(NSURLSession * _Nonnull session) {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.backgroundSessionCompletionHandler) {
void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;
appDelegate.backgroundSessionCompletionHandler = nil;
completionHandler();
}
NSLog(#"All tasks are finished");
}];
For more information please see my answer : How to keep downloading new images in background even if user force quits the app in iOS objective C?
I`m trying to down keyboard before do a NSURLResquest and loading show...
[self.txtComentario resignFirstResponder];
crashes de app...I have already tried to resignFirstResponder inside loadingThread() too
-(void) loadingThread {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[self.myLoadingView setFrame:CGRectMake(0, 0, 320, 568)];
[self.myLoadingImagem setFrame:CGRectMake(133, 250, 54, 9)];
[appDelegate.window addSubview:self.myLoadingView];
[appDelegate.window addSubview:self.myLoadingImagem];
[self.myLoadingView setHidden:NO];
[self animar];
}
-(IBAction)btnComentarClick:(id)sender {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[self.txtComentario resignFirstResponder];
[NSThread detachNewThreadSelector:#selector(loadingThread) toTarget:self withObject:nil];
NSString* comentarios = [kBaseURL stringByAppendingPathComponent:kComentarios];
NSURL* url = [NSURL URLWithString:comentarios]; //1
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = #"POST"; //2
// NSDictionary *usuarioDict = [[NSDictionary alloc] initWithObjectsAndKeys:txtEmailCadastro.text, #"email", txtSenhaCadastro.text, #"senha", categorias, #"categorias", nil];
NSMutableDictionary* jsonable = [NSMutableDictionary dictionary];
safeSet(jsonable, #"idUsuario", appDelegate.usuarioLogado.identificador);
safeSet(jsonable, #"nomeUsuario", appDelegate.usuarioLogado.nome);
safeSet(jsonable, #"textoComentario", self.txtComentario.text);
safeSet(jsonable, #"idOcorrencia", _location._id);
NSData* data = [NSJSONSerialization dataWithJSONObject:jsonable options:0 error:NULL]; //3
request.HTTPBody = data;
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"]; //4
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession* session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { //5
if (!error) {
// NSArray* responseArray = #[[NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]];
NSLog(#"comentado");
dispatch_async(dispatch_get_main_queue(), ^(void){
self.txtComentario.text = #"";
[self.txtComentario resignFirstResponder];
});
}
}];
[dataTask resume];
[self listarComentarios];
}
EDIT: if I try to resignFirstesponder before NSThread, nothing happens, no crash but not keyboard Down..If i try inside loadingThread...the app crashes
the error inside NSThread is:
[UIKeyboardTaskQueue waitUntilAllTasksAreFinished] may only be called
from the main thread.'
It happens sometimes that asynchronous API requests won't call back to the delegate on the main thread. So, just try to ensure that you are on Main thread. If you aren't on it then try to switch to the main thread before you make any update to the UI.
if ([NSThread isMainThread]) {
NSLog(#"Yes, it is!");
} else {
NSLog(#"No, it's not. Please switch to main");
}
try to replace with this code
[self.view endEditing: YES];
I am beginner iOS apps developer .I have tried following link codes.It's playing good but I need selected audio file path and how to upload to server in selected audio,kindly help out.Audio code Reference url
-(IBAction)clickFileuploadbtn:(id)sender;
{
NSLog(#"2");
picker1 =
[[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
picker1.delegate = self;
picker1.allowsPickingMultipleItems = YES;
picker1.prompt = NSLocalizedString (#"Add songs to play", "Prompt in media item picker");
// The media item picker uses the default UI style, so it needs a default-style
// status bar to match it visually
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault animated: YES];
[self presentModalViewController: picker1 animated: YES];
[picker1 release];
// [Uploads FileUpload];
}
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
[self dismissModalViewControllerAnimated: YES];
NSLog(#"%# %d",mediaItemCollection,mediaItemCollection.count);
NSArray *newMediaItem= [mediaItemCollection items];
MPMediaItem *item=[[newMediaItem objectAtIndex:0] retain];
[self uploadMusicFile:item];
}
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker
{
[self dismissModalViewControllerAnimated: YES];
NSLog(#"cancel");
}
- (void) uploadMusicFile:(MPMediaItem *)song
{
NSURL *url = [song valueForProperty: MPMediaItemPropertyAssetURL];
// Given some file path URL: NSURL *pathURL
// Note: [pathURL isFileURL] must return YES
NSString *path = [NSString stringWithFormat:#"%#",url];
NSLog(#"path %#",path);
NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
NSLog(#"data %#" ,data);
NSString *audioName = #"myAudio.caf";
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:#"http://192.168.1.176:1001/api?type=iphoneupload"]];
[request addData:data withFileName:audioName andContentType:#"audio/caf" forKey:#"audioFile"];
[request setDelegate:self];
[request setTimeOutSeconds:500];
[request setDidFinishSelector:#selector(uploadRequestFinished:)];
[request setDidFailSelector:#selector(uploadRequestFailed:)];
[request startAsynchronous];
}
- (void)uploadRequestFinished:(ASIHTTPRequest *)request
{
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = NO;
NSData *webData = [[NSData alloc] initWithData:[request responseData]];
NSString *strEr = [[NSString alloc] initWithData:webData encoding:NSUTF8StringEncoding];
NSLog(#"strEr %#",strEr);
}
- (void) uploadRequestFailed:(ASIHTTPRequest *)request
{
NSLog(#"responseStatusCode %i",[request responseStatusCode]);
NSLog(#"responseString %#",[request responseString]);
NSError *error = [request error];
NSLog(#"error %#",error);
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = NO;
}