Es teóricamente posible grabar una llamada de teléfono en el iPhone?

Estoy aceptando respuestas que:

  • puede o no requerir el teléfono para ser liberado
  • puede o no puede pasar las pautas de apple por el uso de la API privada (que no me importa; no es para la App Store)
  • puede o no puede usar privado Sdk

No quiero respuestas solo sin rodeos diciendo: «Apple no lo permite».
Sé que no habría manera oficial de hacerlo, y ciertamente no para una aplicación App Store, y sé que hay aplicaciones de grabación de llamadas que realicen llamadas salientes a través de sus propios servidores.

InformationsquelleAutor Adam Dempsey | 2009-11-27

5 Comentarios

  1. 72

    Aquí tienes. Completo ejemplo de trabajo. Tweak debe ser cargado en mediaserverd demonio. Se hará el registro de cada llamada de teléfono en /var/mobile/Media/DCIM/result.m4a. Archivo de Audio de dos canales. A la izquierda está el micrófono, a la derecha del altavoz. En el iPhone 4S llamada se registra sólo cuando el altavoz está encendido. En el iPhone 5, 5C y 5S llamada se registra en ambos sentidos. Puede haber pequeñas hipo al cambiar a/de orador, pero la grabación continuará.

    #import <AudioToolbox/AudioToolbox.h>
    #import <libkern/OSAtomic.h>
    //CoreTelephony.framework
    extern "C" CFStringRef const kCTCallStatusChangeNotification;
    extern "C" CFStringRef const kCTCallStatus;
    extern "C" id CTTelephonyCenterGetDefault();
    extern "C" void CTTelephonyCenterAddObserver(id ct, void* observer, CFNotificationCallback callBack, CFStringRef name, void *object, CFNotificationSuspensionBehavior sb);
    extern "C" int CTGetCurrentCallCount();
    enum
    {
    kCTCallStatusActive = 1,
    kCTCallStatusHeld = 2,
    kCTCallStatusOutgoing = 3,
    kCTCallStatusIncoming = 4,
    kCTCallStatusHanged = 5
    };
    NSString* kMicFilePath = @"/var/mobile/Media/DCIM/mic.caf";
    NSString* kSpeakerFilePath = @"/var/mobile/Media/DCIM/speaker.caf";
    NSString* kResultFilePath = @"/var/mobile/Media/DCIM/result.m4a";
    OSSpinLock phoneCallIsActiveLock = 0;
    OSSpinLock speakerLock = 0;
    OSSpinLock micLock = 0;
    ExtAudioFileRef micFile = NULL;
    ExtAudioFileRef speakerFile = NULL;
    BOOL phoneCallIsActive = NO;
    void Convert()
    {
    //File URLs
    CFURLRef micUrl = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)kMicFilePath, kCFURLPOSIXPathStyle, false);
    CFURLRef speakerUrl = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)kSpeakerFilePath, kCFURLPOSIXPathStyle, false);
    CFURLRef mixUrl = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)kResultFilePath, kCFURLPOSIXPathStyle, false);
    ExtAudioFileRef micFile = NULL;
    ExtAudioFileRef speakerFile = NULL;
    ExtAudioFileRef mixFile = NULL;
    //Opening input files (speaker and mic)
    ExtAudioFileOpenURL(micUrl, &micFile);
    ExtAudioFileOpenURL(speakerUrl, &speakerFile);
    //Reading input file audio format (mono LPCM)
    AudioStreamBasicDescription inputFormat, outputFormat;
    UInt32 descSize = sizeof(inputFormat);
    ExtAudioFileGetProperty(micFile, kExtAudioFileProperty_FileDataFormat, &descSize, &inputFormat);
    int sampleSize = inputFormat.mBytesPerFrame;
    //Filling input stream format for output file (stereo LPCM)
    FillOutASBDForLPCM(inputFormat, inputFormat.mSampleRate, 2, inputFormat.mBitsPerChannel, inputFormat.mBitsPerChannel, true, false, false);
    //Filling output file audio format (AAC)
    memset(&outputFormat, 0, sizeof(outputFormat));
    outputFormat.mFormatID = kAudioFormatMPEG4AAC;
    outputFormat.mSampleRate = 8000;
    outputFormat.mFormatFlags = kMPEG4Object_AAC_Main;
    outputFormat.mChannelsPerFrame = 2;
    //Opening output file
    ExtAudioFileCreateWithURL(mixUrl, kAudioFileM4AType, &outputFormat, NULL, kAudioFileFlags_EraseFile, &mixFile);
    ExtAudioFileSetProperty(mixFile, kExtAudioFileProperty_ClientDataFormat, sizeof(inputFormat), &inputFormat);
    //Freeing URLs
    CFRelease(micUrl);
    CFRelease(speakerUrl);
    CFRelease(mixUrl);
    //Setting up audio buffers
    int bufferSizeInSamples = 64 * 1024;
    AudioBufferList micBuffer;
    micBuffer.mNumberBuffers = 1;
    micBuffer.mBuffers[0].mNumberChannels = 1;
    micBuffer.mBuffers[0].mDataByteSize = sampleSize * bufferSizeInSamples;
    micBuffer.mBuffers[0].mData = malloc(micBuffer.mBuffers[0].mDataByteSize);
    AudioBufferList speakerBuffer;
    speakerBuffer.mNumberBuffers = 1;
    speakerBuffer.mBuffers[0].mNumberChannels = 1;
    speakerBuffer.mBuffers[0].mDataByteSize = sampleSize * bufferSizeInSamples;
    speakerBuffer.mBuffers[0].mData = malloc(speakerBuffer.mBuffers[0].mDataByteSize);
    AudioBufferList mixBuffer;
    mixBuffer.mNumberBuffers = 1;
    mixBuffer.mBuffers[0].mNumberChannels = 2;
    mixBuffer.mBuffers[0].mDataByteSize = sampleSize * bufferSizeInSamples * 2;
    mixBuffer.mBuffers[0].mData = malloc(mixBuffer.mBuffers[0].mDataByteSize);
    //Converting
    while (true)
    {
    //Reading data from input files
    UInt32 framesToRead = bufferSizeInSamples;
    ExtAudioFileRead(micFile, &framesToRead, &micBuffer);
    ExtAudioFileRead(speakerFile, &framesToRead, &speakerBuffer);
    if (framesToRead == 0)
    {
    break;
    }
    //Building interleaved stereo buffer - left channel is mic, right - speaker
    for (int i = 0; i < framesToRead; i++)
    {
    memcpy((char*)mixBuffer.mBuffers[0].mData + i * sampleSize * 2, (char*)micBuffer.mBuffers[0].mData + i * sampleSize, sampleSize);
    memcpy((char*)mixBuffer.mBuffers[0].mData + i * sampleSize * 2 + sampleSize, (char*)speakerBuffer.mBuffers[0].mData + i * sampleSize, sampleSize);
    }
    //Writing to output file - LPCM will be converted to AAC
    ExtAudioFileWrite(mixFile, framesToRead, &mixBuffer);
    }
    //Closing files
    ExtAudioFileDispose(micFile);
    ExtAudioFileDispose(speakerFile);
    ExtAudioFileDispose(mixFile);
    //Freeing audio buffers
    free(micBuffer.mBuffers[0].mData);
    free(speakerBuffer.mBuffers[0].mData);
    free(mixBuffer.mBuffers[0].mData);
    }
    void Cleanup()
    {
    [[NSFileManager defaultManager] removeItemAtPath:kMicFilePath error:NULL];
    [[NSFileManager defaultManager] removeItemAtPath:kSpeakerFilePath error:NULL];
    }
    void CoreTelephonyNotificationCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
    {
    NSDictionary* data = (NSDictionary*)userInfo;
    if ([(NSString*)name isEqualToString:(NSString*)kCTCallStatusChangeNotification])
    {
    int currentCallStatus = [data[(NSString*)kCTCallStatus] integerValue];
    if (currentCallStatus == kCTCallStatusActive)
    {
    OSSpinLockLock(&phoneCallIsActiveLock);
    phoneCallIsActive = YES;
    OSSpinLockUnlock(&phoneCallIsActiveLock);
    }
    else if (currentCallStatus == kCTCallStatusHanged)
    {
    if (CTGetCurrentCallCount() > 0)
    {
    return;
    }
    OSSpinLockLock(&phoneCallIsActiveLock);
    phoneCallIsActive = NO;
    OSSpinLockUnlock(&phoneCallIsActiveLock);
    //Closing mic file
    OSSpinLockLock(&micLock);
    if (micFile != NULL)
    {
    ExtAudioFileDispose(micFile);
    }
    micFile = NULL;
    OSSpinLockUnlock(&micLock);
    //Closing speaker file
    OSSpinLockLock(&speakerLock);
    if (speakerFile != NULL)
    {
    ExtAudioFileDispose(speakerFile);
    }
    speakerFile = NULL;
    OSSpinLockUnlock(&speakerLock);
    Convert();
    Cleanup();
    }
    }
    }
    OSStatus(*AudioUnitProcess_orig)(AudioUnit unit, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData);
    OSStatus AudioUnitProcess_hook(AudioUnit unit, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData)
    {
    OSSpinLockLock(&phoneCallIsActiveLock);
    if (phoneCallIsActive == NO)
    {
    OSSpinLockUnlock(&phoneCallIsActiveLock);
    return AudioUnitProcess_orig(unit, ioActionFlags, inTimeStamp, inNumberFrames, ioData);
    }
    OSSpinLockUnlock(&phoneCallIsActiveLock);
    ExtAudioFileRef* currentFile = NULL;
    OSSpinLock* currentLock = NULL;
    AudioComponentDescription unitDescription = {0};
    AudioComponentGetDescription(AudioComponentInstanceGetComponent(unit), &unitDescription);
    //'agcc', 'mbdp' - iPhone 4S, iPhone 5
    //'agc2', 'vrq2' - iPhone 5C, iPhone 5S
    if (unitDescription.componentSubType == 'agcc' || unitDescription.componentSubType == 'agc2')
    {
    currentFile = &micFile;
    currentLock = &micLock;
    }
    else if (unitDescription.componentSubType == 'mbdp' || unitDescription.componentSubType == 'vrq2')
    {
    currentFile = &speakerFile;
    currentLock = &speakerLock;
    }
    if (currentFile != NULL)
    {
    OSSpinLockLock(currentLock);
    //Opening file
    if (*currentFile == NULL)
    {
    //Obtaining input audio format
    AudioStreamBasicDescription desc;
    UInt32 descSize = sizeof(desc);
    AudioUnitGetProperty(unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &desc, &descSize);
    //Opening audio file
    CFURLRef url = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)((currentFile == &micFile) ? kMicFilePath : kSpeakerFilePath), kCFURLPOSIXPathStyle, false);
    ExtAudioFileRef audioFile = NULL;
    OSStatus result = ExtAudioFileCreateWithURL(url, kAudioFileCAFType, &desc, NULL, kAudioFileFlags_EraseFile, &audioFile);
    if (result != 0)
    {
    *currentFile = NULL;
    }
    else
    {
    *currentFile = audioFile;
    //Writing audio format
    ExtAudioFileSetProperty(*currentFile, kExtAudioFileProperty_ClientDataFormat, sizeof(desc), &desc);
    }
    CFRelease(url);
    }
    else
    {
    //Writing audio buffer
    ExtAudioFileWrite(*currentFile, inNumberFrames, ioData);
    }
    OSSpinLockUnlock(currentLock);
    }
    return AudioUnitProcess_orig(unit, ioActionFlags, inTimeStamp, inNumberFrames, ioData);
    }
    __attribute__((constructor))
    static void initialize()
    {
    CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, CoreTelephonyNotificationCallback, NULL, NULL, CFNotificationSuspensionBehaviorHold);
    MSHookFunction(AudioUnitProcess, AudioUnitProcess_hook, &AudioUnitProcess_orig);
    }

    Un par de palabras acerca de lo que está pasando. AudioUnitProcess función se utiliza para el procesamiento de los flujos de audio con el fin de aplicar algunos efectos, mezcla de, convertir etc. Estamos enganchando AudioUnitProcess para acceder a la llamada de teléfono de flujos de audio. Mientras la llamada está activa estas corrientes están siendo procesados en diversas formas.

    Estamos escuchando para CoreTelephony notificaciones con el fin de obtener la llamada de teléfono de los cambios de estado. Cuando recibimos muestras de audio que necesitamos para determinar de dónde vienen – micrófono o el altavoz. Esto se hace usando componentSubType campo en AudioComponentDescription estructura. Ahora, usted podría pensar, ¿por qué no almacenamos AudioUnit objetos de modo que no necesitamos comprobar componentSubType cada vez. Yo hice eso, pero se va a romper todo cuando se altavoz interruptor de encendido/apagado en el iPhone 5 porque AudioUnit de objetos a cambio, ellos se vuelven a crear. Así que ahora nos abra los archivos de audio (uno para el micrófono y un altavoz) y escribir las muestras en ellos, así de simple. Cuando los extremos de una llamada telefónica nos recibirán CoreTelephony notificación y cierre los archivos. Tenemos dos archivos separados con audio desde el micrófono y el altavoz que tenemos que unir. Esto es lo que void Convert() es para. Es bastante simple si usted sabe de la API. Creo que no es necesario explicarlo, los comentarios son suficientes.

    Acerca de los bloqueos. Hay muchos hilos en mediaserverd. El procesamiento de Audio y CoreTelephony las notificaciones en los diferentes subprocesos, por lo que necesitamos algún tipo de sincronización. Elegí los bloqueos de giro, debido a su rapidez y porque la posibilidad de que la contención de bloqueo es pequeño en nuestro caso. En el iPhone 4S e incluso iPhone 5 todo el trabajo en AudioUnitProcess debe hacerse lo más rápido posible, de lo contrario, usted escuchará el hipo de dispositivo de altavoz que obviamente no es buena.

    • Exáctamente lo que yo estaba buscando!
    • Aquí tienes. Completo ejemplo de trabajo probado en el iPhone 4S (iOS 6) y el iPhone 5 (iOS 7). Más tarde serán las pruebas en 5C y 5S. Voy a publicar los resultados.
    • Yo sé poco de la mediaserverd demonio, pero esta respuesta seguramente llena mi conocimiento hambre cerebro. Espero que la lectura de este más de cerca en el fin de semana!
    • Ahora trabaja en 5C y 5S. Estos dispositivos utilizan AudioUnits con diferentes componentSubType.
    • Creo que sólo hay una cosa a la izquierda – que sea compatible con las llamadas de conferencia. De que manera puedo manejar las llamadas de teléfono de notificaciones por ahora, no funciona con las llamadas de conferencia.
    • Es bueno saberlo! 🙂
    • Añadido conferencia de llamadas de soporte.
    • esto va a funcionar en un dispositivo con jailbreak no?
    • no, sólo funcionan en un dispositivo con jailbreak.
    • tengo, gracias @creker 🙂
    • Me puedes ayudar a ejecutar este tweak? Cuando intento ejecutarlo recibo varios errores extraños.¿Cómo puedo compilar y ejecutar este código?
    • Estoy recibiendo este error el uso de identificador no declarado ‘AudioUnitprocess’ ‘
    • Por favor me ayudan con mi pregunta.He sido atrapado en él durante días stackoverflow.com/questions/22525908/…
    • hola, podría plz explicar por qué en el Iphone 4s sólo funciona en modo de altavoz? gracias
    • No sé. Yo gancho método que el proceso de los flujos de audio con varios filtros/Dsp. Sospecho que en el 4S altavoz no requiere ningún procesamiento, para mi enganchado método no es ser llamado a todos. No he tratado de resolverlo así que no te puedo ayudar con eso.
    • Oh, lo siento, no llama enganchado método en modo normal. La grabación de la llamada en el 4S solo funciona con el altavoz.
    • saludos, probablemente no vale la pena invertir tiempo en él desde el iphone4s es bastante viejo y estoy a punto de agarrar un iPhone nuevo de lo que se viene en la próxima versión.
    • Ya estamos en un muy bajo nivel ahora mismo. Estamos enganchando bajo nivel C de procesamiento de audio API que se llama en el interior de mediaserverd demonio que trata con todo el sonido en iOS de todos los demás procesos. Inferior que es el núcleo. De hecho, no vale la pena. No tengo ganas de ingeniería inversa mediaserverd sólo para que cuando todo funciona en dispositivos nuevos.
    • Puede alguien por favor me guía que ¿cómo debo crear tweak con este código. Estoy usando iOSOpendev con xCode 5.0.
    • Hola estoy tratando de manipular los datos de voz que viene después de este ejemplo, por Favor echa un vistazo a mi pregunta aquí stackoverflow.com/questions/29329578/…
    • También he probado en el iPhone 4 y no parece llamar la enganchado audiounitprocess. Lo hace a pesar de triger CoreTelephonyNotificationCallback
    • ¿Cómo hacemos esto? «Tweak debe ser cargado en mediaserverd demonio»? Esto sucede automáticamente después de hacer la instalación? O cómo?
    • He utilizado theos/bin/nic.pl para crear el tweak, y tienen un Tweak.xm archivo. Dónde tengo que poner este código en relación con ese archivo? E. g., puedo reemplazar Ajustar.xm contenidos en este código? O?
    • lo que marcos/bibliotecas deben estar vinculados a resolver los errores de vinculación? hastebin.com/zojadatiwe.avrasm
    • AudioToolbox, CoreTelephony
    • leer esto cydiasubstrate.com/inject/darwin
    • mi recordtweak.plist tiene esto: Filter = { Ejecutables = («mediaserverd»); Modo = «Ninguna»; }; Esto no funciona: gist.github.com/adaptivedev/9ea5ad4c75ca55d1098d
    • Cualquier persona que busca un proyecto de trabajo, por favor, eche un vistazo a aquí
    • Corregido pequeño bug. kCTCallStatusOutgoing se envía demasiado temprano y no debe ser utilizado para iniciar la grabación. Debido a que las unidades de audio no son exclusivos para las llamadas, son el audio general de unidades de procesamiento, que puede ser configurado de forma diferente cuando kCTCallStatusOutgoing es recibido. Es decir, la frecuencia de muestreo puede ser diferente (44100 lugar de 16000). Poco después de kCTCallStatusOutgoing pero antes de kCTCallStatusActive que está siendo configurado propiedad para manejar el audio de la llamada. Que conduce a error cuando uno de los archivos de salida uso incorrecto de la velocidad de muestreo. Cuando te la juegas todo va a ser acelerado.
    • usted dice que no funciona en la no-iPhone con jailbreak. Podrías explicar por qué? (edit: lo siento, sólo se sentó en que este ajuste debe ser cargado en un sistema de proceso. No importa de mí…)
    • el código parece fuera de fecha. Podrías actualizar tu respuesta?
    • si te refieres a iOS 10, entonces yo no prueba en ella. Si alguien la tiene, por favor informe de la espalda y voy a actualizar la respuesta.
    • Sí, trato de ejecutar código con Xcode 8.2.1(iOS 10), pero tengo algún problema en él. Si puede, por favor podría hacer una actualización de su código?
    • es esta solución aceptada por Apple para la presentación, y si es que no va a funcionar para los no-teléfonos desbloqueados?
    • todavía trabajando ??? necesidad de JB o no ?
    • Hola soy errores como «Implícito dism de la función ‘FillOutASBDForLPCM’ no es válida en C99» & «Implícito dism de la función ‘MSHookFunction’ no es válida en C99». por favor ayuda estoy atrapado, también trató de declarar la misma como «extern void MSHookFunction(void símbolo*, void *gancho, void **edad); por tanto el método», pero sin éxito.

  2. 9

    Sí. Grabador De Audio por un desarrollador llamado Limneos hace eso (y bastante bien). Lo puedes encontrar en Cydia. Se puede grabar cualquier tipo de llamada en el iPhone 5 y sin utilizar ninguno de los servidores, etc’. La llamada se coloca en el dispositivo en un archivo de Audio. También es compatible con el iPhone 4S, pero para sólo altavoz.

    Este tweak es conocido por ser el primer tweak vez que llegó a grabar dos secuencias de audio sin usar la 3ª parte de los servidores, VOIP o algo similar.

    El desarrollador colocado pitidos en el otro lado de la llamada para alertar a la persona que está grabando, pero aquellos que fueron retirados por los hackers a través de la red. Para responder a su pregunta, Sí, es muy posible, y no sólo teóricamente.

    ¿Cómo puedo grabar una conversación /llamada de teléfono en iOS?

    Leer más

    • Gran respuesta. Sin embargo, esta es obsoleta ya que si no es compatible con iOS 7 y el iphone 5s.
    • Quien dijo que no es compatible con iOS 7 y el iPhone 5s? Funciona bien aquí en el iPhone 5 con iOS 7 + es compatible con el iPhone 5S. 🙂
    • Ah. He leído mal en combo con el iOS 6 capturas de pantalla. 🙂
    • Hay algún código para que esta fuera en el abierto?
    • No que yo sepa.
    • Pero ¿cómo se las arreglan para hacer esto? Tengo hambre de conocimiento.
    • Supongo que Un montón de prueba & error, un montón de tocar el violín con Manzanas api privada y, posiblemente, algunos de bajo nivel de la c a la cola de todo junto. github.com/nst/iOS-Runtime-Headers
    • permítanos continuar esta discusión en el chat
    • Fuiste capaz de ejecutar el código(El que se concedió la recompensa).Si es así puede que me apunte en la dirección correcta en ¿cómo puedo compilar y ejecutar el código?
    • ¿por qué están comentando en este post?

  3. 7

    La única solución que se me ocurre es usar el Núcleo De Telefonía marco, y más específicamente la callEventHandler de la propiedad, para interceptar cuando hay una llamada entrante y, a continuación, utilizar un AVAudioRecorder para grabar la voz de la persona con el teléfono (y tal vez un poco de la persona en la otra línea de voz). Esto obviamente no es perfecto, y solo funciona si la aplicación está en primer plano en el momento de la llamada, pero puede ser el mejor que usted puede conseguir. Ver más sobre averiguar si hay una llamada de teléfono aquí: Podemos desencadena un evento cuando siempre hay Entrante y Saliente de la llamada en el iphone?.

    EDICIÓN:

    .h:

    #import <AVFoundation/AVFoundation.h>
    #import<CoreTelephony/CTCallCenter.h>
    #import<CoreTelephony/CTCall.h>
    @property (strong, nonatomic) AVAudioRecorder *audioRecorder;

    ViewDidLoad:

    NSArray *dirPaths;
    NSString *docsDir;
    dirPaths = NSSearchPathForDirectoriesInDomains(
    NSDocumentDirectory, NSUserDomainMask, YES);
    docsDir = dirPaths[0];
    NSString *soundFilePath = [docsDir
    stringByAppendingPathComponent:@"sound.caf"];
    NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
    NSDictionary *recordSettings = [NSDictionary
    dictionaryWithObjectsAndKeys:
    [NSNumber numberWithInt:AVAudioQualityMin],
    AVEncoderAudioQualityKey,
    [NSNumber numberWithInt:16],
    AVEncoderBitRateKey,
    [NSNumber numberWithInt: 2],
    AVNumberOfChannelsKey,
    [NSNumber numberWithFloat:44100.0],
    AVSampleRateKey,
    nil];
    NSError *error = nil;
    _audioRecorder = [[AVAudioRecorder alloc]
    initWithURL:soundFileURL
    settings:recordSettings
    error:&error];
    if (error)
    {
    NSLog(@"error: %@", [error localizedDescription]);
    } else {
    [_audioRecorder prepareToRecord];
    }
    CTCallCenter *callCenter = [[CTCallCenter alloc] init];
    [callCenter setCallEventHandler:^(CTCall *call) {
    if ([[call callState] isEqual:CTCallStateConnected]) {
    [_audioRecorder record];
    } else if ([[call callState] isEqual:CTCallStateDisconnected]) {
    [_audioRecorder stop];
    }
    }];

    AppDelegate.m:

    - (void)applicationDidEnterBackground:(UIApplication *)application//Makes sure that the recording keeps happening even when app is in the background, though only can go for 10 minutes.
    {
    __block UIBackgroundTaskIdentifier task = 0;
    task=[application beginBackgroundTaskWithExpirationHandler:^{
    NSLog(@"Expiration handler called %f",[application backgroundTimeRemaining]);
    [application endBackgroundTask:task];
    task=UIBackgroundTaskInvalid;
    }];

    Esta es la primera vez que el uso de muchas de estas características, así que no estoy seguro si esto es exactamente correcto, pero creo que se entiende la idea. No ha sido probado, ya que no tienen acceso a las herramientas adecuadas en el momento. Compilado el uso de estas fuentes:

    • Me gusta la idea. Me encantaría ver en el código, aunque! 🙂
    • Esto es muy theoreticall. Cualquier código que viene?
    • Yo no soy capaz de probar esto antes de que la recompensa extremos. Por lo que es altamente theoreticall.
    • Ah, muy mal. Maldito Apple! 🙂
    • Es posible conseguir este récord de más larga duración – como 2 horas o más ?
  4. 3

    Apple no lo permite y no proporciona ninguna API para él.

    Sin embargo, en un dispositivo con jailbreak estoy seguro de que es posible. Como cuestión de hecho, creo que ya está hecho. Recuerdo haber visto a una aplicación cuando mi teléfono estaba liberado que cambió su voz y registrada la llamada – recuerdo que era una empresa estadounidense que ofrece sólo en los estados unidos. Por desgracia no recuerdo el nombre…

    • Sí creo que ese tipo de Aplicación sólo funciona con las llamadas salientes como la ruta de las llamadas a través de sus servidores, registro de como se pasa a través. Hay un par de aplicaciones similares disponibles en Cydia.
    • Sí, yo estaba hablando de SpoofApp, como TechZen señaló.
    • Sí, SpoofApp probablemente registros en sus servidores porque es en la AppStore y de los registros de las llamadas. De todos modos, estoy seguro de que usted puede grabar las llamadas en un iPhone con jailbreak. Es un equipo. Usted puede hacer cualquier cosa que usted desea cuando usted tiene acceso sin restricciones (y las habilidades requeridas).
    • No necesariamente. Podría ser que la parte de teléfono del iPhone omite el software.
    • Ningún software en todos? Podría ser. Incluso en ese caso, ya que tienes acceso al micrófono que podrían ser datos de las encuestas de ella y en la grabación de… de todos Modos, estas son suposiciones salvajes aquí. Alguien con experiencia en dispositivos con jailbreak, probablemente, podría ilustrarnos más.
    • Echa un vistazo a mi respuesta. Hay una aplicación en Cydia que hace muy bien.

  5. 2

    Supongo que algo de hardware podría solucionar esto. Conectado a la minijack-puerto; tener auriculares y un micrófono que pasa a través de una pequeña grabadora. Esta grabadora puede ser muy simple. Mientras no está en la conversación de la grabadora podría alimentar el teléfono con los datos del/de la grabación (a través de la jack-cable). Y con un simple botón de inicio (al igual que el volum controles de los auriculares), podría ser suficiente para el momento de la grabación.

    Algunas configuraciones

Dejar respuesta

Please enter your comment!
Please enter your name here