npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-native-kookit

v0.3.9

Published

React Native module for intercepting volume button presses on iOS and Android, with FTP client functionality

Readme

react-native-kookit

A comprehensive React Native/Expo module with multiple utilities for Android and iOS.

Features

  • 🎵 Volume Key Interception - Capture volume button presses on both iOS and Android
  • 📁 FTP Client - Full-featured FTP client with upload/download capabilities
  • 🗂️ SMB Client - Access SMB/CIFS network shares
  • 📱 Content URI Handler (Android) - Handle content:// URIs from other apps, bypassing permission restrictions
  • 🔊 Audio Detection (Android) - Detect if any audio is currently playing (music, TTS, videos, etc.)

Content URI Handler

The Content URI Handler solves a common Android problem: when receiving files via "Open with" or "Share" intents, apps receive content:// URIs that often trigger SecurityException: Permission Denial errors.

Key Benefits:

  • ✅ Bypass permission restrictions using Android's ContentResolver
  • ✅ No READ_EXTERNAL_STORAGE permission needed
  • ✅ Works with all third-party apps and file managers
  • ✅ Get file metadata (name, size, MIME type)
  • ✅ Copy to app cache directory for further processing

📖 View Content URI Handler Documentation

Audio Detection

The Audio Detection API allows you to check if the device is currently playing any audio, including music, TTS, videos, or any other audio source.

Key Benefits:

  • ✅ Detect any audio playback (music, TTS, videos, games)
  • ✅ Simple synchronous API
  • ✅ No permissions required
  • ✅ Lightweight and fast
  • ✅ Perfect for audio queue management

Quick Example:

import ReactNativeKookit from "react-native-kookit";

// Check if audio is playing
const isPlaying = ReactNativeKookit.isAudioPlaying();
console.log("Audio playing:", isPlaying);

// Monitor audio state
setInterval(() => {
  const playing = ReactNativeKookit.isAudioPlaying();
  console.log("Audio status:", playing ? "Playing" : "Idle");
}, 500);

📖 View Audio Detection Documentation

API documentation

Installation in managed Expo projects

For managed Expo projects, please follow the installation instructions in the API documentation for the latest stable release. If you follow the link and there is no documentation available then this library is not yet usable within managed projects — it is likely to be included in an upcoming Expo SDK release.

Installation in bare React Native projects

For bare React Native projects, you must ensure that you have installed and configured the expo package before continuing.

Add the package to your npm dependencies

npm install react-native-kookit

Configure for Android

Step 1: Update MainActivity

Your MainActivity.kt (or MainActivity.java) needs to implement the VolumeKeyInterceptActivity interface and override the dispatchKeyEvent method.

For Kotlin (MainActivity.kt):

package com.yourapp.yourpackage

import android.os.Build
import android.os.Bundle
import android.view.KeyEvent

import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate

import expo.modules.ReactActivityDelegateWrapper
import expo.modules.kookit.VolumeKeyInterceptActivity
import expo.modules.kookit.handleVolumeKeyEvent

class MainActivity : ReactActivity(), VolumeKeyInterceptActivity {
    private var volumeKeyListener: ((Int) -> Unit)? = null
    private var isVolumeKeyInterceptEnabled = false

    override fun onCreate(savedInstanceState: Bundle?) {
        // Set the theme to AppTheme BEFORE onCreate to support
        // coloring the background, status bar, and navigation bar.
        // This is required for expo-splash-screen.
        setTheme(R.style.AppTheme);
        super.onCreate(null)
    }

    /**
     * Returns the name of the main component registered from JavaScript.
     */
    override fun getMainComponentName(): String = "main"

    /**
     * Returns the instance of the [ReactActivityDelegate].
     */
    override fun createReactActivityDelegate(): ReactActivityDelegate {
        return ReactActivityDelegateWrapper(
              this,
              BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
              object : DefaultReactActivityDelegate(
                  this,
                  mainComponentName,
                  fabricEnabled
              ){})
    }

    /**
      * Align the back button behavior with Android S
      */
    override fun invokeDefaultOnBackPressed() {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
            if (!moveTaskToBack(false)) {
                super.invokeDefaultOnBackPressed()
            }
            return
        }
        super.invokeDefaultOnBackPressed()
    }

    // Volume key interception implementation
    override fun setVolumeKeyListener(listener: ((Int) -> Unit)?) {
        volumeKeyListener = listener
    }

    override fun setVolumeKeyInterceptEnabled(enabled: Boolean) {
        isVolumeKeyInterceptEnabled = enabled
    }

    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
        if (isVolumeKeyInterceptEnabled && handleVolumeKeyEvent(event)) {
            return true
        }
        return super.dispatchKeyEvent(event)
    }
}

For Java (MainActivity.java):

package com.yourapp.yourpackage;

import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;

import expo.modules.ReactActivityDelegateWrapper;
import expo.modules.kookit.VolumeKeyInterceptActivity;
import expo.modules.kookit.VolumeKeyInterceptActivityKt;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;

public class MainActivity extends ReactActivity implements VolumeKeyInterceptActivity {
    private Function1<Integer, Unit> volumeKeyListener;
    private boolean isVolumeKeyInterceptEnabled = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.AppTheme);
        super.onCreate(null);
    }

    @Override
    protected String getMainComponentName() {
        return "main";
    }

    @Override
    protected ReactActivityDelegate createReactActivityDelegate() {
        return new ReactActivityDelegateWrapper(
            this,
            BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
            new DefaultReactActivityDelegate(this, getMainComponentName(), DefaultNewArchitectureEntryPoint.getFabricEnabled())
        );
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
            if (!moveTaskToBack(false)) {
                super.invokeDefaultOnBackPressed();
            }
            return;
        }
        super.invokeDefaultOnBackPressed();
    }

    @Override
    public void setVolumeKeyListener(Function1<Integer, Unit> listener) {
        this.volumeKeyListener = listener;
    }

    @Override
    public void setVolumeKeyInterceptEnabled(boolean enabled) {
        this.isVolumeKeyInterceptEnabled = enabled;
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (isVolumeKeyInterceptEnabled && VolumeKeyInterceptActivityKt.handleVolumeKeyEvent(this, event)) {
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
}

Configure for iOS

Run npx pod-install after installing the npm package.

Usage

import ReactNativeKookit from "react-native-kookit";

// Add event listener for volume button presses
ReactNativeKookit.addListener("onVolumeButtonPressed", (event) => {
  console.log("Volume button pressed:", event.key); // 'up' or 'down'
});

// Enable volume key interception
ReactNativeKookit.enableVolumeKeyInterception();

// Later, when you want to disable it
ReactNativeKookit.disableVolumeKeyInterception();

// Don't forget to remove listeners when component unmounts
const subscription = ReactNativeKookit.addListener(
  "onVolumeButtonPressed",
  handler
);
// Later: subscription.remove();

API

Methods

  • enableVolumeKeyInterception() - Enable volume button interception
  • disableVolumeKeyInterception() - Disable volume button interception
  • hello() - Returns a greeting string (for testing)
  • setValueAsync(value: string) - Test async function

Events

  • onVolumeButtonPressed - Fired when volume button is pressed
    • event.key - Either 'up' or 'down'

Constants

  • PI - The value of π (for testing)

Troubleshooting

Android

If volume key interception is not working on Android:

  1. Make sure your MainActivity implements VolumeKeyInterceptActivity interface
  2. Make sure you override dispatchKeyEvent method correctly
  3. Ensure you're calling handleVolumeKeyEvent in the dispatchKeyEvent method

iOS

Volume key interception should work automatically on iOS after installation.

Example

See the example directory for a complete working example.

Contributing

Contributions are very welcome! Please refer to guidelines described in the contributing guide.