<|start_filename|>example/App.js<|end_filename|>
import React, {useEffect, useState } from 'react';
import {
  Text,
  Platform,
  Button,
  StyleSheet,
  SafeAreaView
} from 'react-native';
import RNVoipCall, { RNVoipPushKit } from 'react-native-voip-call';

const IsIos = Platform.OS === 'ios';

const log = (data) => console.log('RNVoipCall===> ',data);


let options = {
  appName:'RNVoip App', // Required
  imageName:  'logo',  //string (optional) in ios Resource Folder
  ringtoneSound : '', //string (optional) If provided, it will be played when incoming calls received
  includesCallsInRecents: false, // boolean (optional) If provided, calls will be shown in the recent calls 
  supportsVideo : true //boolean (optional) If provided, whether or not the application supports video calling (Default: true)
}
// Initlize Call Kit IOS is Required
RNVoipCall.initializeCall(options).then(()=>{
 //Success Call Back
}).catch(e=>console.log(e));





const App = () => {
  const [pushkitToken, setPushkitToken] = useState(''); 
  const [callStatus ,setCallStatus] = useState('no call initlized');
  
  
  useEffect(()=>{  
    iosPushKit(); 
    callKit();
    rnVoipCallListners();
  },[])
  
  
  
  const rnVoipCallListners = async () => {
    RNVoipCall.onCallAnswer(data => {
     setCallStatus('call Answed')
      console.log(data);
    });
    
    RNVoipCall.onEndCall(data=> {
     setCallStatus('call Ended');
     console.log("call endede",data);
    })
  } 
  
  
  
  const iosPushKit = () => {
    if(IsIos){
      //For Push Kit
      RNVoipPushKit.requestPermissions();              // --- optional, you can use another library to request permissions
       //Ios PushKit device token Listner
      RNVoipPushKit.getPushKitDeviceToken((res) => {
        if(res.platform === 'ios'){
            setPushkitToken(res.deviceToken)
        }
       });
       //On Remote Push notification Recived in Forground
       RNVoipPushKit.RemotePushKitNotificationReceived((notification)=>{
           log(notification);
       });
    }
  }
  
  
  const callKit = () => { 
    let options = {
      appName:'RNVoip App', // Required
      imageName:  'logo',  //string (optional) in ios Resource Folder
      ringtoneSound : '', //string (optional) If provided, it will be played when incoming calls received
      includesCallsInRecents: false, // boolean (optional) If provided, calls will be shown in the recent calls 
      supportsVideo : true //boolean (optional) If provided, whether or not the application supports video calling (Default: true)
    }
    // Initlize Call Kit IOS is Required
    RNVoipCall.initializeCall(options).then(()=>{
     //Success Call Back
    }).catch(e=>console.log(e));
  
  }
  
  const displayIncommingCall = () => {
    let callOptions = {
      callerId:'825f4094-a674-4765-96a7-1ac512c02a71', // Important uuid must in this format
       ios:{
        phoneNumber:'12344', // Caller Mobile Number
        name:'Ajith', // caller Name
        hasVideo:true
       },
       android:{
        ringtuneSound: true, // defualt true
        ringtune: 'ringtune', // add file inside Project_folder/android/app/res/raw
        duration: 20000, // defualt 30000
        vibration: true, // defualt is true
        channel_name: 'call1asd', // 
        notificationId: 1121,
        notificationTitle: 'Incomming Call',
        notificationBody: 'Some One is Calling...',
        answerActionTitle: 'Answer',
        declineActionTitle: 'Decline',
    
        missedCallTitle: '<NAME>',
        missedCallBody: 'You have a Missed Call From <NAME>'
       }
     }

     RNVoipCall.displayIncomingCall(callOptions).then((data)=>{
       console.log(data)
     }).catch(e=>console.log(e))
    
    
  }
  
  
  const showMissedCall = () => {
    RNVoipCall.showMissedCallNotification("title","body","user-id");
  }
  
  const stopCallNotification = () => {
    RNVoipCall.endAllCalls();
  }
  
  const playRingtune = () => {
    if(!IsIos){
      let options = { 
        fileName: 'filename', // file inside android/app/src/main/res/raw 
        loop:true // looping the Ringtune
      }
      RNVoipCall.playRingtune(options.fileName, options.loop);   
    }
  }
  
  const stopRingtune = () => {
    if(!IsIos){
      RNVoipCall.stopRingtune();
    }
  }
  
  
  return (
      <SafeAreaView style={styles.container}>
        <Text>
          {"push kit token:" + pushkitToken}
        </Text>
        <Text>{`call Status: ${callStatus}`}</Text>
        <Button onPress={()=>displayIncommingCall()} title="Show Incomming Call" />
        <Button onPress={()=>showMissedCall()} title="Show Missed Call" />
        <Button title="end Call " onPress={() => stopCallNotification()} />
        
        <Button title="Show MissedCall" onPress={() => showMissedCall()} />
        <Button title="Play Ringtune (Android only)" onPress={() => playRingtune()} />
        <Button title="stop Ringtune (Android only)" onPress={() => stopRingtune()} />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
    justifyContent: 'space-between',
    maxHeight:'70%'
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 1,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 0,
  },
  button: {
    margin: 2
  }
});

export default App;


<|start_filename|>index.js<|end_filename|>
'use strict';

import { NativeModules, DeviceEventEmitter, Platform } from 'react-native';

import RNVoipPushKitNativeModule from './lib/iosPushKit';
import RNVoipCallNativeModule from './lib/RNVoipCall';

export const RNVoipPushKit = RNVoipPushKitNativeModule;

export default RNVoipCallNativeModule;

<|start_filename|>android/src/main/java/com/ajith/voipcall/RNVoipRingtunePlayer.java<|end_filename|>
package com.ajith.voipcall;

import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;

import com.facebook.react.bridge.ReadableMap;

public class RNVoipRingtunePlayer {
    private static RNVoipRingtunePlayer sInstance;
        private Context mContext;
        private MediaPlayer mMediaPlayer;

        public RNVoipRingtunePlayer(Context context) {
            mContext = context;
        }

        public static RNVoipRingtunePlayer getInstance(Context context) {
            if (sInstance == null) {
                sInstance = new RNVoipRingtunePlayer(context);
            }
            return sInstance;
        }

        public void playMusic(ReadableMap jsonObject) {
            String fileName = jsonObject.getString("ringtune");
            notificationRingtune(fileName);
            mMediaPlayer.setLooping(true);
            if(!mMediaPlayer.isPlaying()){
                mMediaPlayer.start();
                cancelWithTimeOut(jsonObject);
            }
        }

        public void notificationRingtune(String fileName){
            int resId;
            Uri sounduri;
            try{
                resId = mContext.getResources().getIdentifier(fileName, "raw", mContext.getPackageName());
                if(resId != 0){
                    sounduri = Uri.parse("android.resource://" + mContext.getPackageName() + "/"+resId);
                }else {
                    sounduri = Uri.parse("android.resource://" + mContext.getPackageName() + "/"+ R.raw.ringtune);
                }

            }catch (Exception e){
                sounduri = Uri.parse("android.resource://" + mContext.getPackageName() + "/"+ R.raw.ringtune);
            }

            mMediaPlayer = MediaPlayer.create(mContext, sounduri);

        }



        public void playRingtune(String fileName,Boolean isLooping){
            notificationRingtune(fileName);
            if(!mMediaPlayer.isPlaying()){
                mMediaPlayer.setLooping(isLooping);
                mMediaPlayer.start();
            }
        }

        public void cancelWithTimeOut(ReadableMap jsonObject){
            int duration = jsonObject.getInt("duration");
            final ReadableMap json = jsonObject;
            new android.os.Handler().postDelayed(
                    new Runnable() {
                        public void run() {
                            if(mMediaPlayer.isPlaying()) {
                                Intent intent = new Intent(mContext, RNVoipBroadcastReciever.class);
                                intent.setAction("callTimeOut");
                                intent.putExtra("callerId", json.getString("callerId"));
                                intent.putExtra("missedCallTitle", json.getString("missedCallTitle"));
                                intent.putExtra("missedCallBody", json.getString("missedCallBody"));
                                mContext.sendBroadcast(intent);
                                stopMusic();
                            }
                        }
                    }, duration);
        }

        public void stopMusic() {
            if(mMediaPlayer != null) {
                mMediaPlayer.stop();
                mMediaPlayer.seekTo(0);
            }
        }
}


<|start_filename|>ios/RNVoipCall/RNVoipPushKit.h<|end_filename|>

#if __has_include("RCTBridgeModule.h")
#import "RCTBridgeModule.h"
#else
#import <React/RCTBridgeModule.h>
#endif  
#import <Foundation/Foundation.h>
#import <PushKit/PushKit.h>

@interface RNVoipPushKit : NSObject <RCTBridgeModule>

typedef void (^RNVoipPushNotificationCompletion)(void);

@property (nonatomic, strong) NSMutableDictionary<NSString *, RNVoipPushNotificationCompletion> *completionHandlers;

- (void)voipRegistration;
- (void)registerUserNotification:(NSDictionary *)permissions;
- (NSDictionary *)checkPermissions;
+ (void)didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type;
+ (void)didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type;
+ (NSString *)getCurrentAppBackgroundState;
+ (void)addCompletionHandler:(NSString *)uuid completionHandler:(RNVoipPushNotificationCompletion)completionHandler;
+ (void)removeCompletionHandler:(NSString *)uuid;

@end  


<|start_filename|>lib/iosPushKit.js<|end_filename|>
'use strict';

import {
    NativeModules,
    DeviceEventEmitter,
    Platform,
} from 'react-native';

var RNVoipPushKit = NativeModules.RNVoipPushKit;

var invariant = require('fbjs/lib/invariant');
var _notifHandlers = new Map();

const IsIOS =  Platform.OS === 'ios';

export default class RNVoipCallNativeModule {
    // voip ios 
    static getPushKitDeviceToken(handler) {
        if(IsIOS){
            RNVoipPushKit.registerVoipToken();
            let type = 'register'
            invariant(
                type === 'register' ,
                'RNVoipCall only supports `register` events'
            );
            var listener;
          if (type === 'register') {
                listener = DeviceEventEmitter.addListener(
                    "voipRemoteNotificationsRegistered",
                    (registrationInfo) => {
                        handler({...registrationInfo, platform:Platform.OS });
                        this.removeEventListener('register')
                    }
                );
            }
            _notifHandlers.set(handler, listener);
        }else{
            handler({ platform:Platform.OS })
        }
    }
    
    
    static RemotePushKitNotificationReceived(handler){
        if(IsIOS){
            let type = 'notification'
            invariant(
                type === 'notification' ,
                'RNVoipCall only supports `register` events'
            );
            var listener;
          if (type === 'notification') {
                listener = DeviceEventEmitter.addListener(
                    'voipRemoteNotificationReceived',
                    (registrationInfo) => {
                        console.log('voipRemoteNotificationReceived' ,registrationInfo);
                        handler({...registrationInfo, platform:Platform.OS });
                        this.removeEventListener('notification')
                    }
                );
            }
            _notifHandlers.set(handler, listener);
        }else{
            handler({ platform:Platform.OS })
        }
        
        
    }
    
    
    /**
     * Removes the event listener. Do this in `componentWillUnmount` to prevent
     * memory leaks
     */
    static removeEventListener(type, handler) {
        invariant(
            type === 'notification' || type === 'register' ,
            'RNVoipPushNotification only supports `notification`, `register` and `localNotification` events'
        );
        var listener = _notifHandlers.get(handler);
        if (!listener) {
            return;
        }
        listener.remove();
        _notifHandlers.delete(handler);
    }

    static requestPermissions(permissions) {
        var requestedPermissions = {};
        if (permissions) {
            requestedPermissions = {
                alert: !!permissions.alert,
                badge: !!permissions.badge,
                sound: !!permissions.sound
            };
        } else {
            requestedPermissions = {
                alert: true,
                badge: true,
                sound: true
            };
        }
        
        if(IsIOS){
            RNVoipPushKit.requestPermissions(requestedPermissions);
        }else{
            return null;
        }
       
    }
    
}