Access and process various types of personal data in Android with a set of easy, uniform, and privacy-friendly APIs.

Overview

Introduction

PrivacyStreams

API Website Download Hex.pm

PrivacyStreams is an Android library for easy and privacy-friendly personal data access and processing. It offers a functional programming model for various types of personal data, including locations, photos, audios, sensors, contacts, messages, and more.

Cite (Bibtex):

@article{li)_imwut17_privacystreams,
  title={PrivacyStreams: Enabling transparency in personal data processing for mobile apps},
  author={Li, Yuanchun and Chen, Fanglin and Li, Toby Jia-Jun and Guo, Yao and Huang, Gang and Fredrikson, Matthew and Agarwal, Yuvraj and Hong, Jason I},
  journal={Proceedings of the ACM on Interactive, Mobile, Wearable and Ubiquitous Technologies},
  volume={1},
  number={3},
  pages={76},
  year={2017},
  publisher={ACM}

}

In PrivacyStreams, all types of personal data can be accessed and processed with a uniform query interface (UQI):

UQI.getData(Provider, Purpose).transform(Transformation).output(Action)

Where Provider, Transformation, Action are built-in functions and Purpose is a description to describe why the data is needed. Developers only need to find the proper functions to form a query. They don't need to deal with the complicated data formats, multi-threading, runtime permissions, etc.

Based on the functions used in the query and the purpose specified by the developer, PrivacyStreams is able to generate a privacy description, which can be a part of the app description or the privacy policy to help users understand what personal data is used in the app and why.

Quick examples

Get email addresses for all contacts.

    /**
     * Get emails addresses for all contacts on the device.
     * Make sure the following line is added to AndroidManifest.xml
     * <uses-permission android:name="android.permission.READ_CONTACTS" />
     */
    public void getEmails(Context context) {
        try {
            List<List<String>> contactEmails = new UQI(context)
                    .getData(Contact.getAll(), Purpose.SOCIAL("recommend friends"))
                    .asList(Contact.EMAILS);
            // Do something with contact emails
            System.out.println("Contact emails: " + contactEmails);
        } catch (PSException e) {
            e.printStackTrace();
        }
    }

Get the current location.

    /**
     * Get the current location.
     * Make sure the following line is added to AndroidManifest.xml
     * <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     */
    public void getCurrentLocation(Context context) {
        try {
            LatLon latLon = new UQI(context)
                    .getData(Geolocation.asCurrent(Geolocation.LEVEL_CITY), Purpose.UTILITY("check weather"))
                    .getFirst(Geolocation.LAT_LON);
            // Do something with geolocation
            Log.d("Location", "" + latLon.getLatitude() + ", " + latLon.getLongitude());
        } catch (PSException e) {
            e.printStackTrace();
        }
    }

Monitor location updates.

    private static final double CENTER_LATITUDE = 40;
    private static final double CENTER_LONGITUDE = -80;
    private static final double RADIUS = 20.0;

    /**
     * Monitor location updates and callback when in a circular area.
     * Make sure the following line is added to AndroidManifest.xml
     * <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     */
    public void geofence(Context context) {
        new UQI(context)
                .getData(Geolocation.asUpdates(10*1000, Geolocation.LEVEL_EXACT), Purpose.GAME("notify user"))
                .setField("inRegion", GeolocationOperators.inCircle(Geolocation.LAT_LON, CENTER_LATITUDE, CENTER_LONGITUDE, RADIUS))
                .onChange("inRegion", new Callback<Boolean>() {
                    @Override
                    protected void onInput(Boolean inRegion) {
                        // Do something when enters/leaves region.
                        Log.d("Geofence", inRegion ? "entering" : "leaving");
                    }
                });
    }

Wait and read incoming SMS messages.

    private static final String SERVER_PHONE_NUMBER = "123456789";
    private static final String AUTH_MESSAGE_PREFIX = "Your code is ";

    /**
     * Wait for SMS messages and read the auth code
     * Make sure the following line is added to AndroidManifest.xml
     * <uses-permission android:name="android.permission.RECEIVE_SMS" />
     */
    public void readAuthSMS(Context context) {
        new UQI(context).getData(Message.asIncomingSMS(), Purpose.UTILITY("two-factor authentication"))
                .filter(Message.TYPE, Message.TYPE_RECEIVED)
                .filter(Message.CONTACT, SERVER_PHONE_NUMBER)
                .filter(StringOperators.contains(Message.CONTENT, AUTH_MESSAGE_PREFIX))
                .ifPresent(Message.CONTENT, new Callback<String>() {
                    @Override
                    protected void onInput(String text) {
                        String authCode = text.substring(13);
                        // Do something with the auth code
                        Log.d("Auth code", authCode);
                    }
                });
    }

Get local images in media storage.

    /**
     * Get local images in media storage.
     * Make sure the following line is added to AndroidManifest.xml
     * <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     */
    public void getLocalImages(Context context) {
        try {
            List<String> filePaths = new UQI(context)
                    .getData(Image.getFromStorage(), Purpose.UTILITY("read photos"))
                    .setField("filePath", ImageOperators.getFilepath(Image.IMAGE_DATA))
                    .asList("filePath");
            // Do something with the images
            Log.d("Image paths", "" + filePaths);
        } catch (PSException e) {
            e.printStackTrace();
        }
    }

Get microphone loudness periodically.

    private static final long DURATION = 10 * 1000; // 10 seconds
    private static final long INTERVAL = 10 * 60 * 1000; // 10 minutes

    /**
     * Get microphone loudness periodically.
     * Make sure the following line is added to AndroidManifest.xml
     * <uses-permission android:name="android.permission.RECORD_AUDIO" />
     */
    public void getLoudnessPeriodically(Context context) {
        new UQI(context)
                .getData(Audio.recordPeriodic(DURATION, INTERVAL), Purpose.HEALTH("monitor sleep"))
                .setField("loudness", AudioOperators.calcLoudness(Audio.AUDIO_DATA))
                .forEach("loudness", new Callback<Double>() {
                    @Override
                    protected void onInput(Double loudness) {
                        // Do something with the loudness value.
                        Log.d("Loudness", "" + loudness + " dB.");
                    }
                });
    }

Installation

Option 1. Using Gradle (recommended for the most users)

Add the following line to build.gradle file under your app module.

dependencies {
    // The following line imports privacystreams library to your app
    compile 'io.github.privacystreams:privacystreams-android-sdk:0.1.7'
}

That's it!

Note that if you want to use Google location service instead of the Android location service, you will need one more step.

Option 2. From source (recommended for contributors)

In Android Studio, the installation involves the following steps:

  1. Clone this project to your computer.
  2. Open your own project, import privacystreams-android-sdk module.
    • Click File -> New -> Import module....
    • Select privacystreams-android-sdk directory as the source directory.
  3. In your app module, add the following line to dependencies:
    • compile project(':privacystreams-android-sdk')

Documentation

LINK

Discussion

Acknowledgments

Comments
  • Exception when launch Monitor IM

    Exception when launch Monitor IM

    Hi, Im testing this library but all times I get this exception. Any help?

    this is my code: ` @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) public static void monitorMessagesIM(Context context){ UQI uqi; Purpose purpose; uqi = new UQI(context); purpose = Purpose.TEST("Examples");

        uqi.getData(Message.asUpdatesInIM(), purpose) // get a live stream of IM message updates.
                .forEach(new Callback<Item>() {
                    @Override
                    protected void onInput(Item input) { // callback with each item.
                        String type = input.getValueByField("type"); // get the value of "type" field.
                        String content = input.getValueByField("content"); // get the value of "content" field.
                        String contact = input.getValueByField("contact"); // get the value of "contact" field.
                        if ("sent".equals(type)) {
                            System.out.println("Sent a message to " + contact + ": " + content);
                        }
                        else if ("received".equals(type)) {
                            System.out.println("Received a message from " + contact + ": " + content);
                        }
                    }
                });
    }`
    

    java.lang.RuntimeException: Unable to start activity ComponentInfo{me.fpy/me.hawkshaw.ui.activities.HomeActivity}: i.a.a.e: Subscriber class d.b.a.b.m.a.b and its super classes have no public methods with the @Subscribe annotation at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3037) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3172) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1906) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6863) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) Caused by: i.a.a.e: Subscriber class d.b.a.b.m.a.b and its super classes have no public methods with the @Subscribe annotation at i.a.a.m.a(:67) at i.a.a.c.b(:136) at d.b.a.b.k.a(:95) at d.b.a.b.g.g(:27) at d.b.a.b.c.a(:26) at d.b.a.b.b.a(:23) at d.b.a.b.l.a(:121) at d.b.a.b.f.a(:60) at d.b.a.b.f.d(:551) at me.hawkshaw.utils.e.a(:33) at me.hawkshaw.ui.activities.HomeActivity.onCreate(:37) at android.app.Activity.performCreate(Activity.java:7149) at android.app.Activity.performCreate(Activity.java:7140) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1288) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3017)

    opened by rupas385 1
  • Convert test app to Java

    Convert test app to Java

    Kotlin seems to have been causing some issues with onboarding new people. Also, I don't think most people know Kotlin, so it will be easier to just use one programming language.

    enhancement 
    opened by KiithNabaal 1
  • PSDebugSocketServer: fix concurrency bug

    PSDebugSocketServer: fix concurrency bug

    Currently PSDebugSocketServer will randomly encounter bad message sent through socket because multiple send() threads might operate the sockets at the same time. This commit makes sockets synchronized.

    opened by yzygitzh 0
  • PSDebugSocketServer: fix concurrency bug

    PSDebugSocketServer: fix concurrency bug

    Currenly PSDebugSocketServer will crash becuase it might add/remove socket while iterating through the HashSet. This commit use CopnOnWriteSet to eliminate the problem.

    opened by yzygitzh 0
  • NPE on normalizePhoneNumber

    NPE on normalizePhoneNumber

    Hi,

    This issue is specific to Xiaomi device may be, because I did not get this on samsung or nexus devices.

    Brand: Xiaomi Model: Redmi Note 4 Orientation: Portrait RAM free: 936.84 MB Disk free: 8.15 GB Version: 7.0 Orientation: Portrait Rooted: No

    I am using: android-sdk:0.1.7 version of the library.

    Below is crash logs.

    04-09 21:38:50.390 9948-9948/packagename D/PrivacyStreams: Trying to evaluate query {SMSMessageListProvider[] --> ByFieldStreamSorter[timestamp] --> PredicateFilter[FieldCompareOperator[$field_gt, timestamp, 0]] --> StreamReverser[] --> PStreamCollector[StreamListCollector[], []]}. Purpose {Social: Finding sms logs} Required Permissions: [android.permission.READ_SMS] 04-09 21:38:50.393 9948-9948/packagename D/PrivacyStreams: Permission granted, evaluating... 04-09 21:38:50.405 9948-9948/packagename D/PrivacyStreams: Evaluated. 04-09 21:38:50.437 9948-10037/packagename E/AndroidRuntime: FATAL EXCEPTION: Thread-19 Process: packagename , PID: 9948 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.replaceAll(java.lang.String, java.lang.String)' on a null object reference at io.github.privacystreams.utils.CommunicationUtils.normalizePhoneNumber(CommunicationUtils.java:9) at io.github.privacystreams.communication.SMSMessageListProvider.provide(SMSMessageListProvider.java:39) at io.github.privacystreams.core.PStreamProvider$1.run(PStreamProvider.java:19)

    Let me know if you need more info. This issue is reproducable 100% of the time.

    Thanks

    bug 
    opened by akashpathak 6
Owner
null
A beautiful set of predefined colors and a set of color methods to make your Android development life easier.

Colours is a port of the Colours Library for iOS made by my good friend Ben Gordon. You can find that project here. Installation Maven Central Colours

Matthew York 634 Dec 28, 2022
Sample project displaying process of OTP validation using firebase

OTP-Validation-using-firebase Sample project displaying process of OTP validation using firebase Screenshots Concepts used Integrated Firebase sdk for

Ankita Gaba 2 Jun 18, 2022
compaKTset is a small library aimed at providing you with the most memory efficient Set implementation for any particular data type of your choosing.

compaKTset is a small library aimed at providing you with the most memory efficient Set implementation for any particular data type of your choosing.

Ignat Beresnev 3 Nov 16, 2021
Preference wrappers for primitive types for Android

Typed Preferences This library for Android provides classes which allow to store and retrieve settings from the preferences. There is an individual cl

Tobias Preuss 189 Nov 25, 2022
A compose friendly way to deal with in app updates on android

In-App update compose A way to make in app updates in compose How to include in your project The library is available via MavenCentral: allprojects {

Stefan Wärting 25 Dec 31, 2022
Firebase Compoe friendly lib

Firebase Compose A set of Compose components to make it easier to use firebase in the composable world Firebase Compose Auth A jetpack compose module

Stefan Wärting 6 Nov 3, 2022
Access to 1000+ colors on android!

Colorize Android quick access to 1000+ pre-loaded @colors! Install Add the dependency to your build.gradle dependencies { compile 'com.cesarferrei

César Ferreira 407 Nov 14, 2022
Scoper - Access any file with zero permission required

Scoper - Access any file with zero permission required With this codebase you will able to access file from your mobile without requiring permission o

Fakhrul Alam Siddiqei 5 Oct 4, 2022
A collection of Android build scripts for various third-party libraries and the tooling to build them

ndkports A collection of Android build scripts for various third-party libraries and the tooling to build them. If you're an Android app developer loo

reSIProcate project 0 Jan 17, 2022
Various useful utilities for Android apps development

Android Commons Various useful utilities for Android apps development. API documentation provided as Javadoc. Usage Add dependency to your build.gradl

Alex Vasilkov 112 Nov 14, 2022
Secure Preference Manager for android. It uses various Encryption to protect your application's Shared Preferences.

Secure-Pref-Manager ##Secure Preference Manager is a simple Library to help you protect your Shared Preferences. Secure Preference Manager for android

Prashant Solanki 72 Nov 25, 2022
🐫🐍🍢🅿 Multiplatform Kotlin library to convert strings between various case formats including Camel Case, Snake Case, Pascal Case and Kebab Case

KaseChange Multiplatform Kotlin library to convert strings between various case formats Supported Case Formats SCREAMING_SNAKE_CASE snake_case PascalC

PearX Team 67 Dec 30, 2022
A collection of small utility functions to make it easier to deal with some otherwise nullable APIs on Android.

requireKTX is a collection of small utility functions to make it easier to deal with some otherwise nullable APIs on Android, using the same idea as requireContext, requireArguments, and other similar Android SDK methods.

Márton Braun 82 Oct 1, 2022
Ethereum indexer and APIs

Rarible Protocol Ethereum Indexers Here is the list of indexers: NFT indexer ERC-20 indexer Order indexer Architecture Every indexer listens to specif

Rarible Protocol 106 Dec 30, 2022
KmmCaching - An application that illustrates fetching data from remote data source and caching it in local storage

An application that illustrates fetching data from remote data source and caching it in local storage for both IOS and Android platforms using Kotlin Multiplatform Mobile and SqlDelight.

Felix Kariuki 5 Oct 6, 2022
An easy-to-use, cross-platform measurement tool that pulls data out of CD pipelines and analysis the four key metrics for you.

Maintained by SEA team, ThoughtWorks Inc. Read this in other languages: English, 简体中文 Table of Contents About the Project Usage How to Compute Contrib

Thoughtworks 277 Jan 7, 2023
A set of helper classes for using dagger 1 with Android components such as Applications, Activities, Fragments, BroadcastReceivers, and Services.

##fb-android-dagger A set of helper classes for using dagger with Android components such as Applications, Activities, Fragments, BroadcastReceivers,

Andy Dennie 283 Nov 11, 2022
A set of lint rules to check for common mistakes when styling and theming on Android

A set of lint rules to check for common mistakes when styling and theming on Android

GuilhE 6 Aug 29, 2022