How to set lock screen , wallpaper and Ringtone programmatically in iPhone? - ios

In iPhone can we set the lock screen, wallpaper and ringtone programmatically?
If Yes, then please let me know how to set them?

This can all be done easily, but will be rejected by Apple.
The ringtone can be changed by altering com.apple.SpringBoard.plist, specifically the ringtone key.
The following code can be used to read the actual ringtone title of custom ringtones (synced by iTunes).
NSMutableDictionary *custDict = [[NSMutableDictionary alloc] initWithContentsOfFile:#"/private/var/mobile/Media/iTunes_Control/iTunes/Ringtones.plist"];
NSMutableDictionary *dictionary = [custDict objectForKey:#"Ringtones"];
NSArray *keys = [dictionary allKeys];
id key = [keys objectAtIndex:indexPath.row];
NSMutableDictionary *customRingtone = [dictionary objectForKey:key];
NSString *name = [customRingtone objectForKey:#"Name"];
cell.textLabel.text = name;
The Wallpapers can be overwritten at:
NSString *homePath1 = #"/private/var/mobile/Library/SpringBoard/HomeBackground.jpg";
NSString *homePath2 = #"/private/var/mobile/Library/SpringBoard/HomeBackgroundPortrait.jpg";
NSString *lockPath1 = #"/private/var/mobile/Library/SpringBoard/LockBackground.jpg";
NSString *lockPath2 = #"/private/var/mobile/Library/SpringBoard/LockBackgroundPortrait.jpg";
These examples were used in one of my Cydia apps. Theres not really much more to them, but these should get you going in the right direction.

The answer by WrightsCS stopped working at some point due to a change in iOS. Unfortunately, this is something you have to live with if you wish to use undocumented features.
If you still need to do this, for non-App Store apps only, this code works in iOS 9.3. It could stop working in any future iOS release, though. (see comment below: no longer working in iOS 10)
#import "SBSUIWallpaperPreviewViewController.h"
#import <dlfcn.h>
// open the private framework dynamically
void *handle = dlopen("/System/Library/PrivateFrameworks/SpringBoardUIServices.framework/SpringBoardUIServices", RTLD_NOW);
UIImage *wallpaper = [UIImage imageNamed: #"background.jpg"];
Class sbClass = NSClassFromString(#"SBSUIWallpaperPreviewViewController");
// we create a view controller, but don't display it.
// just use it to load image and set wallpaper
SBSUIWallpaperPreviewViewController *controller = (SBSUIWallpaperPreviewViewController*)[[sbClass alloc] initWithImage: wallpaper];
[controller setWallpaperForLocations: 3]; // 3 -> set both for lock screen and home screen
dlclose(handle);
You'll need to add the private API header to your project. You can usually find these online with a little searching, for example, here.
In the example above, [SBSUIWallpaperPreviewViewController setWallpaperForLocations:] is called with an argument of 3: 3 indicates the image should be used for both lock and home screens. 1 indicates Lock screen only. 2 indicates Home screen only.
For an explanation of why I open this framework up dynamically, see my related answer here.
I don't have an answer regarding ringtones. This really should be a separate question: completely different APIs at work.

use private api if you can
check PLStaticWallpaperImageViewController

Related

iMessage App - iOS 10 localParticipantIdentifier.UUIDString does not translate in simulator

Below is a snippet showing adding a subcaption to a previously created MSMessage. Upon running in the simulator, the string prefixed with $ does not translate to the contact name as expected.
Bug in my code?
MSMessageTemplateLayout *templateLayout = [[MSMessageTemplateLayout alloc] init];
NSString *messageText = [NSString stringWithFormat:#"Challenged by $%#",
currentConversation.localParticipantIdentifier.UUIDString];
[templateLayout setSubcaption:messageText];
There is an open radar for it: https://openradar.appspot.com/26877873

Make App Activities and States Searchable by using NSUserActivity

Following is the code that I am trying to implement to make app activities and states searchable but not able to show on iOS search
NSUserActivity *userActivity = [[NSUserActivity alloc]initWithActivityType:#"com.mycompany.activity-type"];
userActivity.title = #"Hello world from in app search";
userActivity.keywords = [NSSet setWithArray:#[#"Hello",#"Welcome", #"search"]];
userActivity.userInfo = #{#"id":#"com.example.state"};
userActivity.eligibleForSearch = YES;
[userActivity becomeCurrent];
Link to make my question more clear.
From the Apple Forums:
One thing that has bitten a few people (myself included) is that the
activity must not be deallocated. If your code is only working with
NSUserActivities (i.e. not using CoreSpotlight in addition) then make
sure your activities aren't being deallocated immediately.
In my
case, I had code that was allocating the NSUA, setting some properties
on it, calling becomeCurrent, but then the object would go out of
scope and deallocated. If you're doing this, try tossing the activity
into a strong property to see if you can then see the results when you
search.
https://forums.developer.apple.com/message/13640#13640
What I have found is you have to assign the NSUserActivity instance you have created to your currently visible UIViewControllers's userActivity property before calling -becomeCurrent. It has fixed it for me and the items immediately appeared both for handoff on other devices and in spotlight search on the same device.
I was experiencing the same issue, and I read on the dev forums that in seed 1 it only works on the device. I was able to make it work on the device.
It might be that this, as with handoff, will only work on the device sadly.
I couldn't get it to work with beta 2 either.
Using a CSSearchableItemAttributeSet with
CSSearchableItemAttributeSet* attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString*)kUTTypeImage];
attributeSet.title = myobject.title;
attributeSet.keywords = [myobject.desc componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
attributeSet.contentDescription = myobject.desc;
if (myobject.images.count > 0) {
attributeSet.thumbnailData = myobject.myimagedata;
}
attributeSet.rating = #(myobject.rating.integerValue / 2);
CSSearchableItem* item;
item = [[CSSearchableItem alloc] initWithUniqueIdentifier:#"..." domainIdentifier:#"..." attributeSet:attributeSet];
[[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:#[item] completionHandler: ^(NSError * __nullable error) {
NSLog(#"Search item indexed");
}];
works, though, even with images.
What I couldn't get to work was the rating to show up anywhere.

Creating multiple themes in an iPhone App

I have recently released my first app to the App Store and still have a very long way to go with iOS development.
I'm looking to introduce themes into my app as an update so the user can select from 4-5 different themes.
I've got a tab bar controller and have set the 5th tab to be the "Settings" tab which contains a Table View with cells. The first cell contains the text "Themes" where the user can select it, be taken to a new Table view/Collection View to select the themes.
So I searched online and came across this incredible answer on doing just this:
How to create Multiple Themes/Skins for iphone apps?
Because I'm still new to development, I'm in need of assistance to take this forward.
To start off with, I have two themes:
1) DefaultTheme (Newiphonebackground.png)
2) PurplePinkTheme (Purplepinknew.png)
Following the instructions, I have created one plist for the Default theme and one plist for the PurplePink theme.
In the ThemeManager class that I created, I have:
- (id)init
{
if ((self = [super init]))
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *themeName = [defaults objectForKey:#"theme"] ?: #"DefaultTheme";
NSString *path = [[NSBundle mainBundle] pathForResource:themeName ofType:#"plist"];
self.styles = [NSDictionary dictionaryWithContentsOfFile:path];
}
return self;
}
+ (ThemeManager *)sharedManager
{
static ThemeManager *sharedManager = nil;
if (sharedManager == nil)
{
sharedManager = [[ThemeManager alloc] init];
}
return sharedManager;
}
In my table view, where the theme will get applied (it's going to get applied to every screen in the app but this is just to start off with where I'm testing with one scene in the app), in the viewDidLoad, I put:
NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:#"DefaultTheme"];
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
self.tableView.backgroundView = backgroundImageView;
That does nothing different because it applies the default theme. However if in the ThemeManager, I change the plist to be:
NSString *themeName = [defaults objectForKey:#"theme"] ?: #"PurplePinkTheme";
and in the viewDidLoad of the separate Table View, I set the code to be:
NSString *imageName = [styles objectForKey:#"PurplePinkTheme"];
Then upon loading my application, my PurplePinkTheme loads.
So far so good, but I don't think I've done anything substantial here.
I am confused from this point on. I am looking to start off with changing just the background images from the in-app settings and once I have that done, I'll look to change the custom navigation bars, etc.
So my questions are:
1) Why do I create one plist per theme?
2) How exactly do I link multiple plists in the ThemeManager class?
3) How do I link all of the themes up to the settings Theme cells allowing the user to choose?
I'm sorry this is vague, but I really need to understand how exactly I can carry on here. For example, I just don't get how to have multiple plists in the ThemeManager and how to move forward from here.
To recap, I, for now just want the ability to have multiple plist files with the different backgrounds, and for the user to go the settings tab in my app, click on the "Themes" cell and be able to select a different theme for the app without restarting the app.
I know the tutorial does carry on with explanations on that, but I'm just not quite sure I understand it all.
Any guidance on this would be massively appreciated.
Many thanks,
Your question is super long so I must confess I did not read the whole thing. That said I spent a lot of time with themes and the best solution I have found is to create an object that handles formatting. This is how I think you can implement it:
Create a formatter object extending NSObject
Have a property for each changeable piece of the theme:
for example if the background changes images you can have a UIImage in there called background. If the font color changes you have a UIFont property in there.
create a shared instance of your formater by adding:
+(Formater *) sharedInstance; //add to .h
+ (Formater *) sharedInstance //add to .m
{
if (!_sharedInstance)
{
_sharedInstance = [[Formater alloc] init];
}
}
Now in your view controller all you need to do is create a reference to your shared item and use that to style your view controller. (remember to make the changes in viewWillAppear not or it will not change after the setting is changed.
Voila!

message sent to deallocated instance using Pinterest SDK

I'm using the Pinterest iOS SDK to share an item in my iPad app. The following snippet of code will always crash with a message sent to deallocated instance on the line with the comment:
NSString *clientId = [NSMutableString stringWithString:#"1431665"];
NSLog(#"clientId: %#", clientId);
Pinterest *pinterest = [[Pinterest alloc] initWithClientId:clientId];
NSLog(#"gone: %#", clientId); // <- CRASH!
I'm using NSMutableString stringWithString to simulate the conditions in my app. I don't actually use that line in my code.
Even if don't output the clientId on the last line, the app crashes when leaving the block. I assume it's because ARC is trying to release the reference which has already been deallocated.
It seems like the Pinterest SDK must be doing something wonky and trashing the string I'm passing in. Is there some way I can get around this while they fix their code?
EDIT 1
Simplified the test case.
EDIT 2
It looks like the Pinterest SDK is consuming the clientId argument. Based on the clang ARC documentation, the way to indicate this to clang is to indicate this with __attribute((ns_consumed)).
New question: Is it possible to indicate this to ARC without modifying the signature of the method to add the attribute?
EDIT 3
So this works, but it's ugly as sin? Is there another way?
NSString *clientId = [NSMutableString stringWithString:#"1431665"];
[clientId performSelector:NSSelectorFromString(#"retain")]; // <- UGLY!
NSLog(#"clientId: %#", clientId);
Pinterest *pinterest = [[Pinterest alloc] initWithClientId:clientId];
NSLog(#"gone: %#", clientId);
What I did was make a static variable that represented the Pinterest class:
//I put this outside my #implementation code at the top of my m file
static Pinterest *_pinterest = nil;
// instantiating
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_pinterest = [[Pinterest alloc] initWithClientId:clientId];
});
I think that Pinterest assumed that everyone would use their class as a static singleton because that's probably what they do internally. To be fair, I don't foresee using multiple client ID's with a single app in most cases. I agree, though, this is a stupefying oversight on their part. They didn't even document this behavior, what were they thinking?!
My current workaround, which seems to be the least hacky of the ideas so far is this wrapper class that doesn't use ARC:
+ (void) createPinWithClientId:(NSString *)clientId
imageURL:(NSURL *)imageURL
sourceURL:(NSURL *)sourceURL
description:(NSString *)descriptionText {
Pinterest *pinterest = [[Pinterest alloc] initWithClientId:clientId];
[pinterest createPinWithImageURL:imageURL
sourceURL:sourceURL
description:descriptionText];
}
The key is to disable ARC for the class, which keeps the runtime from deallocating the clientId.

Control UIView on Load

Hi everybody I am trying to make an app with a login page and profile page.
So i am using two view for them : login_view and profile_view
So login_view is my view in nib file i.e default view.
but i want to check if the user has already signed in before in viewdidLoad method like session and show him profile_view instead when app starts.
Can Anybody help me in it?
I tried this but failed
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
if ([array count] == 0)
{
NSNumber * uud = [array objectAtIndex:0];
[self.view = home];
}
Might want to use a keychain. If not, you could run the risk of having unauthorized access. Lot's of other reasons too.
This sample app by Apple should help you:
http://developer.apple.com/library/ios/#samplecode/GenericKeychain/Introduction/Intro.html

Resources