diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 45147a5..279ecb5 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,10 +1,13 @@ + package="com.audacious_software.pdk.passivedatakit" + xmlns:tools="http://schemas.android.com/tools"> + + diff --git a/build.gradle b/build.gradle index 483f432..3dbd2ce 100755 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,7 @@ buildscript { repositories { jcenter() maven { url "https://jitpack.io" } + maven { url 'https://dl.bintray.com/rvalerio/maven' } flatDir{ dirs 'libs' } @@ -28,7 +29,7 @@ android { useLibrary 'org.apache.http.legacy' defaultConfig { - minSdkVersion 19 + minSdkVersion 18 targetSdkVersion 25 versionCode 1 versionName "1.0" @@ -54,11 +55,11 @@ android { compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:recyclerview-v7:25.3.1' compile 'com.android.support:cardview-v7:25.3.1' - compile 'com.google.android.gms:play-services-location:10.2.1' - compile 'com.google.android.gms:play-services-maps:10.2.1' - compile 'com.google.android.gms:play-services-nearby:10.2.1' - compile 'com.google.android.gms:play-services-places:10.2.1' - compile 'com.google.android.gms:play-services-awareness:10.2.1' + compile 'com.google.android.gms:play-services-location:10.2.4' + compile 'com.google.android.gms:play-services-maps:10.2.4' + compile 'com.google.android.gms:play-services-nearby:10.2.4' + compile 'com.google.android.gms:play-services-places:10.2.4' + compile 'com.google.android.gms:play-services-awareness:10.2.4' compile 'com.google.maps.android:android-maps-utils:0.4' compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'commons-io:commons-io:2.4' @@ -66,6 +67,7 @@ android { compile 'org.apache.commons:commons-lang3:3.4' compile 'com.fasterxml.jackson.core:jackson-core:2.7.3' compile 'com.github.philjay:mpandroidchart:v3.0.1' + compile 'com.rvalerio:fgchecker:1.0.1' } buildTypes { diff --git a/res/drawable-hdpi/ic_foreground_apps.png b/res/drawable-hdpi/ic_foreground_apps.png new file mode 100755 index 0000000..4879c67 Binary files /dev/null and b/res/drawable-hdpi/ic_foreground_apps.png differ diff --git a/res/drawable-mdpi/ic_foreground_apps.png b/res/drawable-mdpi/ic_foreground_apps.png new file mode 100755 index 0000000..f34723a Binary files /dev/null and b/res/drawable-mdpi/ic_foreground_apps.png differ diff --git a/res/drawable-xhdpi/ic_foreground_apps.png b/res/drawable-xhdpi/ic_foreground_apps.png new file mode 100755 index 0000000..ba91b51 Binary files /dev/null and b/res/drawable-xhdpi/ic_foreground_apps.png differ diff --git a/res/drawable-xxhdpi/ic_foreground_apps.png b/res/drawable-xxhdpi/ic_foreground_apps.png new file mode 100755 index 0000000..7c69935 Binary files /dev/null and b/res/drawable-xxhdpi/ic_foreground_apps.png differ diff --git a/res/drawable-xxxhdpi/ic_foreground_apps.png b/res/drawable-xxxhdpi/ic_foreground_apps.png new file mode 100755 index 0000000..4a34272 Binary files /dev/null and b/res/drawable-xxxhdpi/ic_foreground_apps.png differ diff --git a/res/layout/card_generator_app_event.xml b/res/layout/card_generator_app_event.xml index cf87fcb..3d822c9 100755 --- a/res/layout/card_generator_app_event.xml +++ b/res/layout/card_generator_app_event.xml @@ -25,7 +25,7 @@ android:layout_width="24dp" android:layout_height="24dp" android:layout_marginRight="8dp" /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/databases.xml b/res/values/databases.xml index fc11dda..9e41810 100755 --- a/res/values/databases.xml +++ b/res/values/databases.xml @@ -27,4 +27,8 @@ CREATE TABLE history(_id INTEGER PRIMARY KEY AUTOINCREMENT, fetched INTEGER, transmitted INTEGER, observed INTEGER, health TEXT, level INTERGER, plugged TEXT, present INTEGER, scale INTEGER, temperature INTEGER, voltage INTEGER, technology TEXT, status TEXT); + + CREATE TABLE history(_id INTEGER PRIMARY KEY AUTOINCREMENT, fetched INTEGER, transmitted INTEGER, observed INTEGER, application TEXT); + ALTER TABLE history ADD duration REAL; + diff --git a/res/values/diagnostics.xml b/res/values/diagnostics.xml index c2807f3..c72f76c 100755 --- a/res/values/diagnostics.xml +++ b/res/values/diagnostics.xml @@ -19,4 +19,7 @@ Access to Withing Account Required Permission is required to fetch data from the Withings server. Please grant this application the requested permissions. + + App Usage Data Permission Required + This app requires access to app usage data from your device\'s settings. diff --git a/res/values/generators.xml b/res/values/generators.xml index c304b38..b4037cd 100755 --- a/res/values/generators.xml +++ b/res/values/generators.xml @@ -149,6 +149,13 @@ #1B5E20 - App Event History + App Events History No app events have been logged yet. + + + Foreground Applications + No application launches have been logged yet. + Most Used (Last 24 Hours) + Recently Used + %1$s: %2$.0fm \ No newline at end of file diff --git a/src/com/audacious_software/passive_data_kit/generators/device/ForegroundApplication.java b/src/com/audacious_software/passive_data_kit/generators/device/ForegroundApplication.java new file mode 100755 index 0000000..4eb5410 --- /dev/null +++ b/src/com/audacious_software/passive_data_kit/generators/device/ForegroundApplication.java @@ -0,0 +1,386 @@ +package com.audacious_software.passive_data_kit.generators.device; + +import android.app.AppOpsManager; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.provider.Settings; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.audacious_software.passive_data_kit.PassiveDataKit; +import com.audacious_software.passive_data_kit.activities.generators.DataPointViewHolder; +import com.audacious_software.passive_data_kit.diagnostics.DiagnosticAction; +import com.audacious_software.passive_data_kit.generators.Generator; +import com.audacious_software.passive_data_kit.generators.Generators; +import com.audacious_software.pdk.passivedatakit.R; +import com.rvalerio.fgchecker.AppChecker; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; + +/** + * Created by cjkarr on 5/10/2017. + */ + +public class ForegroundApplication extends Generator{ + + private static final String GENERATOR_IDENTIFIER = "pdk-foreground-application"; + + private static final String ENABLED = "com.audacious_software.passive_data_kit.generators.device.ForegroundApplication.ENABLED"; + private static final boolean ENABLED_DEFAULT = true; + + private static int DATABASE_VERSION = 2; + + private static final String TABLE_HISTORY = "history"; + private static final String HISTORY_OBSERVED = "observed"; + private static final String HISTORY_APPLICATION = "application"; + private static final String HISTORY_DURATION = "duration"; + + private static ForegroundApplication sInstance = null; + + private Context mContext = null; + + private static final String DATABASE_PATH = "pdk-foreground-application.sqlite"; + + private SQLiteDatabase mDatabase = null; + private long mSampleInterval = 15000; + private AppChecker mAppChecker = null; + + public static ForegroundApplication getInstance(Context context) { + if (ForegroundApplication.sInstance == null) { + ForegroundApplication.sInstance = new ForegroundApplication(context.getApplicationContext()); + } + + return ForegroundApplication.sInstance; + } + + public ForegroundApplication(Context context) { + super(context); + + this.mContext = context.getApplicationContext(); + } + + public static void start(final Context context) { + ForegroundApplication.getInstance(context).startGenerator(); + } + + private void startGenerator() { + final ForegroundApplication me = this; + + if (this.mAppChecker != null) { + this.mAppChecker.stop(); + + this.mAppChecker = null; + } + + this.mAppChecker = new AppChecker(); + this.mAppChecker.other(new AppChecker.Listener() { + @Override + public void onForeground(String process) { + Log.e("PDK", "PROCESS: " + process); + + long now = System.currentTimeMillis(); + + ContentValues values = new ContentValues(); + values.put(ForegroundApplication.HISTORY_OBSERVED, now); + values.put(ForegroundApplication.HISTORY_APPLICATION, process); + values.put(ForegroundApplication.HISTORY_DURATION, me.mSampleInterval); + + me.mDatabase.insert(ForegroundApplication.TABLE_HISTORY, null, values); + + Bundle update = new Bundle(); + update.putLong(ForegroundApplication.HISTORY_OBSERVED, now); + update.putString(ForegroundApplication.HISTORY_APPLICATION, process); + update.putLong(ForegroundApplication.HISTORY_DURATION, me.mSampleInterval); + + Generators.getInstance(me.mContext).notifyGeneratorUpdated(ForegroundApplication.GENERATOR_IDENTIFIER, update); + } + }); + + this.mAppChecker.timeout((int) this.mSampleInterval); + this.mAppChecker.start(this.mContext); + + File path = PassiveDataKit.getGeneratorsStorage(this.mContext); + + path = new File(path, ForegroundApplication.DATABASE_PATH); + + this.mDatabase = SQLiteDatabase.openOrCreateDatabase(path, null); + + int version = this.getDatabaseVersion(this.mDatabase); + + switch (version) { + case 0: + this.mDatabase.execSQL(this.mContext.getString(R.string.pdk_generator_foreground_applications_create_history_table)); + case 1: + this.mDatabase.execSQL(this.mContext.getString(R.string.pdk_generator_foreground_applications_history_table_add_duration)); + } + + this.setDatabaseVersion(this.mDatabase, ForegroundApplication.DATABASE_VERSION); + + Generators.getInstance(this.mContext).registerCustomViewClass(ForegroundApplication.GENERATOR_IDENTIFIER, ForegroundApplication.class); + } + + public static boolean isEnabled(Context context) { + SharedPreferences prefs = Generators.getInstance(context).getSharedPreferences(context); + + return prefs.getBoolean(ForegroundApplication.ENABLED, ForegroundApplication.ENABLED_DEFAULT); + } + + public static boolean isRunning(Context context) { + if (ForegroundApplication.sInstance == null) { + return false; + } + + return ForegroundApplication.sInstance.mAppChecker != null; + } + + public static ArrayList diagnostics(final Context context) { + ArrayList actions = new ArrayList<>(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + int mode = appOps.checkOpNoThrow("android:get_usage_stats", android.os.Process.myUid(), context.getPackageName()); + + if (mode != AppOpsManager.MODE_ALLOWED) { + actions.add(new DiagnosticAction(context.getString(R.string.diagnostic_usage_stats_permission_required_title), context.getString(R.string.diagnostic_usage_stats_permission_required), new Runnable() { + @Override + public void run() { + context.startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); + } + })); + } + } + + return actions; + } + + public static void bindViewHolder(DataPointViewHolder holder) { + final Context context = holder.itemView.getContext(); + + long lastTimestamp = 0; + + ForegroundApplication generator = ForegroundApplication.getInstance(holder.itemView.getContext()); + + Cursor c = generator.mDatabase.query(ForegroundApplication.TABLE_HISTORY, null, null, null, null, null, ForegroundApplication.HISTORY_OBSERVED + " DESC"); + + while (c.moveToNext()) { + if (lastTimestamp == 0) { + lastTimestamp = c.getLong(c.getColumnIndex(ForegroundApplication.HISTORY_OBSERVED)); + } + } + + c.close(); + + View cardContent = holder.itemView.findViewById(R.id.card_content); + View cardEmpty = holder.itemView.findViewById(R.id.card_empty); + TextView dateLabel = (TextView) holder.itemView.findViewById(R.id.generator_data_point_date); + + long now = System.currentTimeMillis(); + long yesterday = now - (24 * 60 * 60 * 1000); + + HashMap appDurations = new HashMap<>(); + HashMap appWhens = new HashMap<>(); + + ArrayList latest = new ArrayList<>(); + + String where = ForegroundApplication.HISTORY_OBSERVED + " > ?"; + String[] args = { "" + yesterday }; + + c = generator.mDatabase.query(ForegroundApplication.TABLE_HISTORY, null, where, args, null, null, ForegroundApplication.HISTORY_OBSERVED); + + while (c.moveToNext()) { + String application = c.getString(c.getColumnIndex(ForegroundApplication.HISTORY_APPLICATION)); + + if (latest.contains(application)) { + latest.remove(application); + } + + latest.add(0, application); + + if (appDurations.containsKey(application) == false) { + appDurations.put(application, 0.0); + } + + double appDuration = appDurations.get(application); + double duration = c.getDouble(c.getColumnIndex(ForegroundApplication.HISTORY_DURATION)); + + long lastObserved = c.getLong(c.getColumnIndex(ForegroundApplication.HISTORY_OBSERVED)); + + appDuration += duration; + + appDurations.put(application, appDuration); + appWhens.put(application, lastObserved); + } + + c.close(); + + double largestUsage = 0.0; + + ArrayList> largest = new ArrayList<>(); + + for (String key : appDurations.keySet()) { + HashMap app = new HashMap<>(); + + double duration = appDurations.get(key); + + app.put(key, duration); + + if (duration > largestUsage) { + largestUsage = duration; + } + + largest.add(app); + } + + Collections.sort(largest, new Comparator>() { + @Override + public int compare(HashMap mapOne, HashMap mapTwo) { + String keyOne = mapOne.keySet().iterator().next(); + String keyTwo = mapTwo.keySet().iterator().next(); + + Double valueOne = mapOne.get(keyOne); + Double valueTwo = mapTwo.get(keyTwo); + + return valueTwo.compareTo(valueOne); + } + }); + + int[] appRowIds = { R.id.application_one, R.id.application_two, R.id.application_three, R.id.application_four }; + int[] whenAppRowIds = { R.id.application_recent_one, R.id.application_recent_two, R.id.application_recent_three, R.id.application_recent_four }; + + while (largest.size() > appRowIds.length) { + largest.remove(largest.size() - 1); + } + + while (latest.size() > whenAppRowIds.length) { + latest.remove(latest.size() - 1); + } + + PackageManager packageManager = context.getPackageManager(); + + if (largest.size() > 0) { + for (int appRowId : appRowIds) { + View row = cardContent.findViewById(appRowId); + + row.setVisibility(View.GONE); + } + + for (int i = 0; i < appRowIds.length && i < largest.size(); i++) { + HashMap appDef = largest.get(i); + int appRowId = appRowIds[i]; + + View row = cardContent.findViewById(appRowId); + row.setVisibility(View.VISIBLE); + + TextView appName = (TextView) row.findViewById(R.id.app_name); + ImageView appIcon = (ImageView) row.findViewById(R.id.application_icon); + + View usedDuration = row.findViewById(R.id.app_used_duration); + View remainderDuration = row.findViewById(R.id.app_remaining_duration); + + for (String key : appDef.keySet()) { + double duration = appDef.get(key); + + try { + String name = packageManager.getApplicationLabel(packageManager.getApplicationInfo(key, PackageManager.GET_META_DATA)).toString(); + + double minutes = duration / (1000 * 60); + + appName.setText(context.getString(R.string.generator_foreground_application_app_name_duration, name, minutes)); + Drawable icon = packageManager.getApplicationIcon(key); + appIcon.setImageDrawable(icon); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + + double remainder = largestUsage - duration; + + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) usedDuration.getLayoutParams(); + params.weight = (float) duration; + usedDuration.setLayoutParams(params); + + params = (LinearLayout.LayoutParams) remainderDuration.getLayoutParams(); + params.weight = (float) remainder; + remainderDuration.setLayoutParams(params); + } + } + + for (int i = 0; i < whenAppRowIds.length && i < latest.size(); i++) { + String appPackage = latest.get(i); + int appRowId = whenAppRowIds[i]; + + View row = cardContent.findViewById(appRowId); + row.setVisibility(View.VISIBLE); + + TextView appName = (TextView) row.findViewById(R.id.app_name); + ImageView appIcon = (ImageView) row.findViewById(R.id.application_icon); + + try { + String name = packageManager.getApplicationLabel(packageManager.getApplicationInfo(appPackage, PackageManager.GET_META_DATA)).toString(); + + appName.setText(name); + Drawable icon = packageManager.getApplicationIcon(appPackage); + appIcon.setImageDrawable(icon); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + + TextView appWhen = (TextView) row.findViewById(R.id.app_last_used); + appWhen.setText(Generator.formatTimestamp(context, appWhens.get(appPackage) / 1000)); + } + + cardContent.setVisibility(View.VISIBLE); + cardEmpty.setVisibility(View.GONE); + + dateLabel.setText(Generator.formatTimestamp(context, lastTimestamp / 1000)); + } else { + cardContent.setVisibility(View.GONE); + cardEmpty.setVisibility(View.VISIBLE); + + dateLabel.setText(R.string.label_never_pdk); + } + } + + @Override + public List fetchPayloads() { + return new ArrayList<>(); + } + + public static View fetchView(ViewGroup parent) + { + return LayoutInflater.from(parent.getContext()).inflate(R.layout.card_generator_foreground_application, parent, false); + } + + public static long latestPointGenerated(Context context) { + long timestamp = 0; + + ForegroundApplication me = ForegroundApplication.getInstance(context); + + Cursor c = me.mDatabase.query(ForegroundApplication.TABLE_HISTORY, null, null, null, null, null, ForegroundApplication.HISTORY_OBSERVED + " DESC"); + + if (c.moveToNext()) { + timestamp = c.getLong(c.getColumnIndex(ForegroundApplication.HISTORY_OBSERVED)); + } + + c.close(); + + return timestamp; + } +} diff --git a/src/com/audacious_software/passive_data_kit/generators/device/Location.java b/src/com/audacious_software/passive_data_kit/generators/device/Location.java index 058f4ec..8d65c12 100755 --- a/src/com/audacious_software/passive_data_kit/generators/device/Location.java +++ b/src/com/audacious_software/passive_data_kit/generators/device/Location.java @@ -10,7 +10,6 @@ import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.database.Cursor; -import android.database.MatrixCursor; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; @@ -27,7 +26,6 @@ import android.support.v7.app.AlertDialog; import android.support.v7.widget.SwitchCompat; import android.util.DisplayMetrics; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -114,7 +112,6 @@ public class Location extends Generator implements GoogleApiClient.ConnectionCal private static Location sInstance = null; private GoogleApiClient mGoogleApiClient = null; - private android.location.Location mLastLocation = null; private long mUpdateInterval = 60000; private SQLiteDatabase mDatabase = null; @@ -657,8 +654,6 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { checked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(final CompoundButton compoundButton, final boolean checked) { - Log.e("PDK", "CHECK CHANGE!"); - final CompoundButton.OnCheckedChangeListener me = this; if (option == Location.ACCURACY_BEST) { @@ -927,8 +922,25 @@ public android.location.Location getLastKnownLocation() { return location; } - if (this.mLastLocation != null) { - return this.mLastLocation; + android.location.Location lastLocation = null; + + Cursor c = this.mDatabase.query(Location.TABLE_HISTORY, null, null, null, null, null, Location.HISTORY_OBSERVED + " DESC"); + + if (c.moveToNext()) { + double latitude = c.getDouble(c.getColumnIndex(Location.HISTORY_LATITUDE)); + double longitude = c.getDouble(c.getColumnIndex(Location.HISTORY_LONGITUDE)); + + lastLocation = new android.location.Location("Passive-Data-Kit"); + lastLocation.setLatitude(latitude); + lastLocation.setLongitude(longitude); + } + + c.close(); + + + + if (lastLocation != null) { + return lastLocation; } LocationManager locations = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); diff --git a/src/com/audacious_software/passive_data_kit/generators/diagnostics/AppEvent.java b/src/com/audacious_software/passive_data_kit/generators/diagnostics/AppEvent.java index 0319140..7d41388 100755 --- a/src/com/audacious_software/passive_data_kit/generators/diagnostics/AppEvent.java +++ b/src/com/audacious_software/passive_data_kit/generators/diagnostics/AppEvent.java @@ -11,11 +11,14 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.webkit.WebView; import android.widget.LinearLayout; import android.widget.TextView; import com.audacious_software.passive_data_kit.PassiveDataKit; +import com.audacious_software.passive_data_kit.activities.DataDisclosureDetailActivity; import com.audacious_software.passive_data_kit.activities.generators.DataPointViewHolder; +import com.audacious_software.passive_data_kit.activities.generators.GeneratorViewHolder; import com.audacious_software.passive_data_kit.diagnostics.DiagnosticAction; import com.audacious_software.passive_data_kit.generators.Generator; import com.audacious_software.passive_data_kit.generators.Generators; @@ -68,9 +71,11 @@ public static void start(final Context context) { AppEvent.getInstance(context).startGenerator(); } - private void startGenerator() { - final AppEvent me = this; + public static String getGeneratorTitle(Context context) { + return context.getString(R.string.generator_app_events); + } + private void startGenerator() { Generators.getInstance(this.mContext).registerCustomViewClass(AppEvent.GENERATOR_IDENTIFIER, AppEvent.class); File path = PassiveDataKit.getGeneratorsStorage(this.mContext); @@ -103,6 +108,16 @@ public static ArrayList diagnostics(Context context) { return new ArrayList<>(); } + public static void bindDisclosureViewHolder(final GeneratorViewHolder holder) { + Class currentClass = new Object() { }.getClass().getEnclosingClass(); + + String identifier = currentClass.getCanonicalName(); + + TextView generatorLabel = (TextView) holder.itemView.findViewById(R.id.label_generator); + + generatorLabel.setText(AppEvent.getGeneratorTitle(holder.itemView.getContext())); + } + public static void bindViewHolder(DataPointViewHolder holder) { final Context context = holder.itemView.getContext(); @@ -188,7 +203,7 @@ public Object instantiateItem(ViewGroup container, int position) { int listPosition = AppEvent.CARD_PAGE_SIZE * position; - for (int i = 0; i < AppEvent.CARD_PAGE_SIZE; i++) { + for (int i = 0; i < AppEvent.CARD_PAGE_SIZE && listPosition + i < events.size(); i++) { Object[] values = events.get(listPosition + i); String event = (String) values[0]; @@ -358,4 +373,31 @@ public boolean logEvent(String eventName, Map eventDet public void logThrowable(Throwable t) { } + + public static List getDisclosureActions(final Context context) { + List actions = new ArrayList<>(); + + DataDisclosureDetailActivity.Action disclosure = new DataDisclosureDetailActivity.Action(); + + disclosure.title = context.getString(R.string.label_data_collection_description); + disclosure.subtitle = context.getString(R.string.label_data_collection_description_more); + + WebView disclosureView = new WebView(context); + disclosureView.loadUrl("file:///android_asset/html/passive_data_kit/generator_app_events_disclosure.html"); + + disclosure.view = disclosureView; + + actions.add(disclosure); + + return actions; + } + + public static View getDisclosureDataView(final GeneratorViewHolder holder) { + final Context context = holder.itemView.getContext(); + + WebView disclosureView = new WebView(context); + disclosureView.loadUrl("file:///android_asset/html/passive_data_kit/generator_app_events_disclosure.html"); + + return disclosureView; + } }