Skip to content

React Native Module that shows data usage per application in Android 4.4+

License

Notifications You must be signed in to change notification settings

shimatai/react-native-android-datausage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React Native Module for Android - Data Usage per App

This React Native module shows data usage per application in Android (required version 4.4 or later). Your React Native app should be able to read Android Data Usage statistics.

alt text

It uses TrafficStats or NetworkStatsManager (requires Android 6.0 or later).

Installing it as a module in your project

There are many ways to do this, here's the way I do it:

  1. Do npm install --save git+https://github.com/shimatai/react-native-android-datausage.git in your React Native main project.

  2. Link the library:

    • Add the following to android/settings.gradle:

      include ':react-native-android-datausage'
      project(':react-native-android-datausage').projectDir = new File(settingsDir, '../node_modules/react-native-android-datausage/android')
      
    • Add the following to android/app/build.gradle:

      ...
      
      dependencies {
          ...
          compile project(':react-native-android-datausage')
      }
    • Add the following to android/app/src/main/java/**/MainApplication.java:

      package com.company.myapp;
      
      import br.com.oi.reactnative.module.datausage.DataUsagePackage;  // add this for react-native-android-datausage
      
      public class MainApplication extends Application implements ReactApplication {
      
          @Override
          protected List<ReactPackage> getPackages() {
              return Arrays.<ReactPackage>asList(
                  new MainReactPackage(),
                  new DataUsagePackage()     // add this for react-native-android-datausage
              );
          }
      }
    • You need to request some specific permissions to user, so add the following permissions to AndroidManifest.xml (don't forget to declare the XML namespace xmlns:tools):

      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              package="com.company.myapp"
              android:versionCode="1"
              android:versionName="1.0">
      
              <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
              <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
              <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
              <uses-permission
                      android:name="android.permission.PACKAGE_USAGE_STATS"
                      tools:ignore="ProtectedPermissions"/>
      
              <permission
                      android:name="android.permission.PACKAGE_USAGE_STATS"
                      android:protectionLevel="signature"/>
      
              ...
      
      </manifest>
    • For Android 6 or later, user needs to allow the requested permissions, so add the following code to android/app/src/main/java/**/MainActivity.java after the method getMainComponentName():

      package com.company.myapp;
      
      import android.Manifest;
      import android.annotation.TargetApi;
      import android.app.AppOpsManager;
      import android.content.Context;
      import android.content.Intent;
      import android.content.pm.PackageManager;
      import android.os.Build;
      import android.provider.Settings;
      import android.support.v4.app.ActivityCompat;
      
      private static final int READ_PHONE_STATE_REQUEST = 37;
      
      ...
      
      @Override
      protected void onResume() {
              super.onResume();
              requestPermissions();
      }
      
      private void requestPermissions() {
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
              if (!hasPermissionToReadNetworkHistory()) {
                      return;
              }
      
              if (!hasPermissionToReadPhoneStats()) {
                      requestPhoneStateStats();
                      return;
              }
          }
      }
      
      private boolean hasPermissionToReadNetworkHistory() {
              if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                      return true;
              }
              final AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
              int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
              android.os.Process.myUid(), getPackageName());
              if (mode == AppOpsManager.MODE_ALLOWED) {
                      return true;
              }
              appOps.startWatchingMode(AppOpsManager.OPSTR_GET_USAGE_STATS,
                      getApplicationContext().getPackageName(),
                      new AppOpsManager.OnOpChangedListener() {
                              @Override
                              @TargetApi(Build.VERSION_CODES.M)
                              public void onOpChanged(String op, String packageName) {
                                      int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), getPackageName());
                                      if (mode != AppOpsManager.MODE_ALLOWED) {
                                              return;
                                      }
                                      appOps.stopWatchingMode(this);
                                      Intent intent = new Intent(MainActivity.this, MainActivity.class);
                                      if (getIntent().getExtras() != null) {
                                              intent.putExtras(getIntent().getExtras());
                                      }
                                      intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                                      getApplicationContext().startActivity(intent);
                              }
              });
              requestReadNetworkHistoryAccess();
              return false;
      }
      
      private boolean hasPermissionToReadPhoneStats() {
              if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_DENIED) {
                      return false;
              } else {
                      return true;
              }
      }
      
      private void requestReadNetworkHistoryAccess() {
              Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
              startActivity(intent);
      }
      
      private void requestPhoneStateStats() {
              ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, READ_PHONE_STATE_REQUEST);
      }
  3. Simply add NativeModules to import this React Native module:

    import { NativeModules } from 'react-native';
    
    if (NativeModules.DataUsageModule) {
        // Get data usage of all installed apps in current device
        // Parameters "startDate" and "endDate" are optional (works only with Android 6.0 or later). Declare empty object {} for no date filter.
        NativeModules.DataUsageModule.listDataUsageByApps({
            "startDate": new Date(2017, 4, 22, 0, 0, 0, 0).getTime(), // 1495422000000 = Mon May 22 2017 00:00:00
            "endDate": new Date().getTime()
        },
        (err, jsonArrayStr) => {
            if (!err) {
    	    var apps = JSON.parse(jsonArrayStr);
    	    console.log(apps);
    	    for (var i = 0; i < apps.length; i++) {
    		    var app = apps[i];
    		    console.log("App name: " + app.name + "\n" 
    				    + "Package name: " + app.packageName + "\n"
    				    + "Received bytes: " + app.rx + "bytes\n"
    				    + "Transmitted bytes: " + app.tx + "bytes\n"
    				    + "Received MB: " + app.rxMb + "\n"
    				    + "Transmitted MB: " + app.txMb);
    	    }
            }
        });
    
        // Get data usage of specific list of installed apps in current device
        // Example: get data usage for Facebook, YouTube and WhatsApp.
        // Parameters "startDate" and "endDate" are optional (works only with Android 6.0 or later)
        NativeModules.DataUsageModule.getDataUsageByApp({
                "packages": ["com.facebook.katana", "com.google.android.youtube", "com.whatsapp"],
                "startDate": new Date(2017, 4, 22, 0, 0, 0, 0).getTime(), // 1495422000000 = Mon May 22 2017 00:00:00
                "endDate": new Date().getTime()
            }, 
            (err, jsonArrayStr) => {
                if (!err) {
    	    var apps = JSON.parse(jsonArrayStr);
    	    console.log(apps);
    	    for (var i = 0; i < apps.length; i++) {
    		    var app = apps[i];
    		    console.log("App name: " + app.name + "\n" 
    				    + "Package name: " + app.packageName + "\n"
    				    + "Received bytes: " + app.rx + "bytes\n"
    				    + "Transmitted bytes: " + app.tx + "bytes\n"
    				    + "Received MB: " + app.rxMb + "\n"
    				    + "Transmitted MB: " + app.txMb);
    	    }
            }
        });
    
        // Check if app has permission to access data usage by apps
        // This way will not ask for permissions (check only)
        // If you pass "requestPermission": "true", then app will ask for permissions.
        NativeModules.DataUsageModule.requestPermissions({ "requestPermission": "false" }, (err, result) => {
            var permissionObj = JSON.parse(result);
            if (!permissionObj.permissions) {
                Alert.alert('Give Permission', 
                            'You need to enable data usage access for this app. Please, enable it on the next screen.',
                        [
                            { text: 'Cancel', style: 'cancel', onPress: () => Actions.pop() },
                            { text: 'Give permission', onPress: () => this.requestPermissions() }
                        ],
                        { cancelable: false });
            }
        });
    }

About

React Native Module that shows data usage per application in Android 4.4+

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •