-
jan4843
I'm trying to follow this tutorial to enable unlimited backgrounding on an app, using the new
objc_util
(in the beta).
Do you think it will work? Is the tutorial still relevant with the latest iOS versions?The code looks pretty simple:
@property (nonatomic, strong) AVPlayer *player;
NSError *sessionError = nil; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&sessionError]; AVPlayerItem *item = [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"silence" withExtension:@"mp3"]]; [self setPlayer:[[AVPlayer alloc] initWithPlayerItem:item]]; // this makes sure our player keeps working after the silence ends [[self player] setActionAtItemEnd:AVPlayerActionAtItemEndNone]; [[self player] play];
I'm not able to fully implement it due to my lack of knowledges. In particular I'm not able to access a class' constant using
objc_util
. -
jan4843
Thanks omz for trying it out! As expected I was missing something (the signature), but unfortunately I don't have a code signing identity to try with a different key.
Thank you for your work. -
jan4843
Once you load the framework you can access the classes you need with
ObjCClass
.You can even call private APIs, but this is useless since iOS 7 because apps must have certain entitlements to be able to trigger certain methods. Here is an example to open Siri (that fails silently).
from objc_util import * # Load the framework ObjCClass('NSBundle').bundleWithPath_('/System/Library/PrivateFrameworks/AccessibilityUtilities.framework').load() # "Import" one of its class AXSpringBoardServer = ObjCClass('AXSpringBoardServer') # Call a class' method AXSpringBoardServer.alloc().openSiri()
About the dynamic library, I can't help you.
-
jan4843
Please don't take my words seriously, I don't have experience and I haven't tested. Maybe this is a solution: you put your framework in Pythonista and then load it.
from objc_util import * ObjCClass('NSBundle').bundleWithPath_('MyFramework.framework').load()
-
jan4843
That's the point, if an app is playing audio it doesn't get “killed”. If you try to run an endless script and meanwhile run some heavy games iOS will “kill” Pythonista and so your script to free up the RAM.
The cool part is that the solution provided by omz does not interfere at all with playing audio in the system.Meanwhile I got my hands back to my Mac and wrote the script I couldn't figure out:
from objc_util import * from time import sleep from datetime import datetime # "Imports" AVAudioSession = ObjCClass('AVAudioSession') AVPlayer = ObjCClass('AVPlayer') AVPlayerItem = ObjCClass('AVPlayerItem') NSURL = ObjCClass('NSURL') # Set Pythonista app to play non-blocking, 'mixed with others' sounds audio_session = AVAudioSession.sharedInstance() audio_session.setCategory_withOptions_error_('AVAudioSessionCategoryPlayback', 1, None) # Create the item to play sound = NSURL.fileURLWithPath_('silence.mp3') item = AVPlayerItem.playerItemWithURL_(sound) # Play the sound (only once) player = AVPlayer.alloc().initWithPlayerItem_(item) player.setActionAtItemEnd_(2) player.play() while True: print 'Still running', datetime.now() sleep(1)
It does seem to work, as the omz’ solution, but I don't know if there is efficiency differences.
-
jan4843
Obelisk, if you use a simple loop, iOS will stop it after 3 minutes because background activities have restrictions. It would also stop when iOS free up the RAM “killing” Pythonista.
-
jan4843
Thank you, omz! The code works for me. What does
sound.Player.number_of_loops = -1
mean? Is the sound played continuously? Does it consume CPU in background?Also, I tried this:
from sound import Player player = Player('') player.number_of_loops = -1 player.play()
and it still works, even with files that doesn't exist.
Sorry, Obelisk, but I don't understand your comment. The idea is to play a silent sound to keep scripts running in the background, forever.