Adding initial app framework
Change-Id: I0c53e3487eb3be1eefa2d0c7f260a90d82fd8844
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..4720ba0
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,99 @@
+import org.apache.tools.ant.taskdefs.condition.Os
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 21
+ buildToolsVersion "21.1.2"
+
+ defaultConfig {
+ applicationId "net.named_data.nfd"
+ minSdkVersion 14
+ targetSdkVersion 21
+ versionCode 2001
+ versionName "0.2.1"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ sourceSets {
+ main {
+ java.srcDirs "src/main/java"
+ res.srcDirs "src/main/res"
+ jniLibs.srcDir 'src/main/libs'
+ jni.srcDirs = [] //disable automatic ndk-build call
+ }
+ androidTest.setRoot('tests')
+ androidTest.java.srcDirs = ['tests/src']
+ }
+
+ splits {
+ abi {
+ enable true // enable ABI split feature to create one APK per ABI
+ universalApk true //generate an additional APK that targets all the ABIs
+ }
+ }
+
+ // map for the version code
+ // versionCode digit for each supported ABI, with 64bit>32bit and x86>armeabi-*
+ project.ext.versionCodes = ['armeabi': 1,
+ 'armeabi-v7a': 2,
+ 'arm64-v8a': 3,
+ 'mips': 5,
+ 'mips64': 6,
+ 'x86': 8,
+ 'x86_64': 9]
+
+ android.applicationVariants.all { variant ->
+ // assign different version code for each output
+ variant.outputs.each { output ->
+ output.versionCodeOverride = project.ext.versionCodes.get(
+ output.getFilter(
+ com.android.build.OutputFile.ABI), 0) * 1000000 +
+ defaultConfig.versionCode
+ }
+ }
+
+ // call regular ndk-build(.cmd) script from app directory
+ task ndkBuild(type: Exec) {
+ commandLine getNdkBuildCmd(), '-C', file('src/main').absolutePath
+ }
+
+ tasks.withType(JavaCompile) {
+ compileTask -> compileTask.dependsOn ndkBuild
+ }
+
+ task cleanNative(type: Exec) {
+ commandLine getNdkBuildCmd(), '-C', file('src/main').absolutePath, 'clean'
+ }
+
+ clean.dependsOn cleanNative
+}
+
+def getNdkBuildCmd() {
+ if (System.env.ANDROID_NDK_ROOT != null)
+ return System.env.ANDROID_NDK_ROOT
+
+ Properties properties = new Properties()
+ properties.load(project.rootProject.file('local.properties').newDataInputStream())
+ String ndk_dir = properties.getProperty('ndk.dir', null)
+ if (ndk_dir == null) {
+ throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file or with an ANDROID_NDK_ROOT environment variable.")
+ }
+
+ String ndk_build = ndk_dir + "/ndk-build"
+ if (Os.isFamily(Os.FAMILY_WINDOWS)) {
+ ndk_build += ".cmd"
+ }
+
+ return ndk_build
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:appcompat-v7:21.0.3'
+ compile 'com.android.support:support-v4:21.0.3'
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3b96635
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="net.named_data.nfd" >
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".NfdSettingsActivity"
+ android:label="@string/app_name" >
+ </activity>
+ </application>
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_LOGS" />
+
+</manifest>
diff --git a/app/src/main/java/net/named_data/nfd/NfdSettingsActivity.java b/app/src/main/java/net/named_data/nfd/NfdSettingsActivity.java
new file mode 100644
index 0000000..a161349
--- /dev/null
+++ b/app/src/main/java/net/named_data/nfd/NfdSettingsActivity.java
@@ -0,0 +1,280 @@
+package net.named_data.nfd;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+import android.preference.RingtonePreference;
+import android.text.TextUtils;
+
+
+import java.util.List;
+
+import net.named_data.nfd.wrappers.Example;
+
+/**
+ * A {@link PreferenceActivity} that presents a set of application settings. On
+ * handset devices, settings are presented as a single list. On tablets,
+ * settings are split by category, with category headers shown to the left of
+ * the list of settings.
+ * <p/>
+ * See <a href="http://developer.android.com/design/patterns/settings.html">
+ * Android Design: Settings</a> for design guidelines and the <a
+ * href="http://developer.android.com/guide/topics/ui/settings.html">Settings
+ * API Guide</a> for more information on developing a Settings UI.
+ */
+public class NfdSettingsActivity extends PreferenceActivity
+{
+ /**
+ * Determines whether to always show the simplified settings UI, where
+ * settings are presented in a single list. When false, settings are shown
+ * as a master/detail two-pane view on tablets. When true, a single pane is
+ * shown on tablets.
+ */
+ private static final boolean ALWAYS_SIMPLE_PREFS = false;
+
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState)
+ {
+ super.onPostCreate(savedInstanceState);
+
+ /// @todo Remove after the example no longer needed
+ Example.main();
+
+ setupSimplePreferencesScreen();
+ }
+
+ /**
+ * Shows the simplified settings UI if the device configuration if the
+ * device configuration dictates that a simplified, single-pane UI should be
+ * shown.
+ */
+ private void setupSimplePreferencesScreen()
+ {
+ if (!isSimplePreferences(this)) {
+ return;
+ }
+
+ // In the simplified UI, fragments are not used at all and we instead
+ // use the older PreferenceActivity APIs.
+
+ // Add 'general' preferences.
+ addPreferencesFromResource(R.xml.pref_general);
+
+ // Add 'notifications' preferences, and a corresponding header.
+ PreferenceCategory fakeHeader = new PreferenceCategory(this);
+ fakeHeader.setTitle(R.string.pref_header_notifications);
+ getPreferenceScreen().addPreference(fakeHeader);
+ addPreferencesFromResource(R.xml.pref_notification);
+
+ // Add 'data and sync' preferences, and a corresponding header.
+ fakeHeader = new PreferenceCategory(this);
+ fakeHeader.setTitle(R.string.pref_header_data_sync);
+ getPreferenceScreen().addPreference(fakeHeader);
+ addPreferencesFromResource(R.xml.pref_data_sync);
+
+ // Bind the summaries of EditText/List/Dialog/Ringtone preferences to
+ // their values. When their values change, their summaries are updated
+ // to reflect the new value, per the Android Design guidelines.
+ bindPreferenceSummaryToValue(findPreference("example_text"));
+ bindPreferenceSummaryToValue(findPreference("example_list"));
+ bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
+ bindPreferenceSummaryToValue(findPreference("sync_frequency"));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onIsMultiPane()
+ {
+ return isXLargeTablet(this) && !isSimplePreferences(this);
+ }
+
+ /**
+ * Helper method to determine if the device has an extra-large screen. For
+ * example, 10" tablets are extra-large.
+ */
+ private static boolean isXLargeTablet(Context context)
+ {
+ return (context.getResources().getConfiguration().screenLayout
+ & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ }
+
+ /**
+ * Determines whether the simplified settings UI should be shown. This is
+ * true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
+ * doesn't have newer APIs like {@link PreferenceFragment}, or the device
+ * doesn't have an extra-large screen. In these cases, a single-pane
+ * "simplified" settings UI should be shown.
+ */
+ private static boolean isSimplePreferences(Context context)
+ {
+ return ALWAYS_SIMPLE_PREFS
+ || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
+ || !isXLargeTablet(context);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public void onBuildHeaders(List<Header> target)
+ {
+ if (!isSimplePreferences(this)) {
+ loadHeadersFromResource(R.xml.pref_headers, target);
+ }
+ }
+
+ /**
+ * A preference value change listener that updates the preference's summary
+ * to reflect its new value.
+ */
+ private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener()
+ {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object value)
+ {
+ String stringValue = value.toString();
+
+ if (preference instanceof ListPreference) {
+ // For list preferences, look up the correct display value in
+ // the preference's 'entries' list.
+ ListPreference listPreference = (ListPreference) preference;
+ int index = listPreference.findIndexOfValue(stringValue);
+
+ // Set the summary to reflect the new value.
+ preference.setSummary(
+ index >= 0
+ ? listPreference.getEntries()[index]
+ : null);
+
+ } else if (preference instanceof RingtonePreference) {
+ // For ringtone preferences, look up the correct display value
+ // using RingtoneManager.
+ if (TextUtils.isEmpty(stringValue)) {
+ // Empty values correspond to 'silent' (no ringtone).
+ preference.setSummary(R.string.pref_ringtone_silent);
+
+ } else {
+ Ringtone ringtone = RingtoneManager.getRingtone(
+ preference.getContext(), Uri.parse(stringValue));
+
+ if (ringtone == null) {
+ // Clear the summary if there was a lookup error.
+ preference.setSummary(null);
+ } else {
+ // Set the summary to reflect the new ringtone display
+ // name.
+ String name = ringtone.getTitle(preference.getContext());
+ preference.setSummary(name);
+ }
+ }
+
+ } else {
+ // For all other preferences, set the summary to the value's
+ // simple string representation.
+ preference.setSummary(stringValue);
+ }
+ return true;
+ }
+ };
+
+ /**
+ * Binds a preference's summary to its value. More specifically, when the
+ * preference's value is changed, its summary (line of text below the
+ * preference title) is updated to reflect the value. The summary is also
+ * immediately updated upon calling this method. The exact display format is
+ * dependent on the type of preference.
+ *
+ * @see #sBindPreferenceSummaryToValueListener
+ */
+ private static void bindPreferenceSummaryToValue(Preference preference)
+ {
+ // Set the listener to watch for value changes.
+ preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
+
+ // Trigger the listener immediately with the preference's
+ // current value.
+ sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
+ PreferenceManager
+ .getDefaultSharedPreferences(preference.getContext())
+ .getString(preference.getKey(), ""));
+ }
+
+ /**
+ * This fragment shows general preferences only. It is used when the
+ * activity is showing a two-pane settings UI.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static class GeneralPreferenceFragment extends PreferenceFragment
+ {
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.pref_general);
+
+ // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+ // to their values. When their values change, their summaries are
+ // updated to reflect the new value, per the Android Design
+ // guidelines.
+ bindPreferenceSummaryToValue(findPreference("example_text"));
+ bindPreferenceSummaryToValue(findPreference("example_list"));
+ }
+ }
+
+ /**
+ * This fragment shows notification preferences only. It is used when the
+ * activity is showing a two-pane settings UI.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static class NotificationPreferenceFragment extends PreferenceFragment
+ {
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.pref_notification);
+
+ // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+ // to their values. When their values change, their summaries are
+ // updated to reflect the new value, per the Android Design
+ // guidelines.
+ bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
+ }
+ }
+
+ /**
+ * This fragment shows data and sync preferences only. It is used when the
+ * activity is showing a two-pane settings UI.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static class DataSyncPreferenceFragment extends PreferenceFragment
+ {
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.pref_data_sync);
+
+ // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+ // to their values. When their values change, their summaries are
+ // updated to reflect the new value, per the Android Design
+ // guidelines.
+ bindPreferenceSummaryToValue(findPreference("sync_frequency"));
+ }
+ }
+}
diff --git a/app/src/main/java/net/named_data/nfd/wrappers/Example.java b/app/src/main/java/net/named_data/nfd/wrappers/Example.java
new file mode 100644
index 0000000..0e70c0a
--- /dev/null
+++ b/app/src/main/java/net/named_data/nfd/wrappers/Example.java
@@ -0,0 +1,13 @@
+package net.named_data.nfd.wrappers;
+
+/**
+ * Created by cawka on 1/27/15.
+ */
+public class Example
+{
+ static {
+ System.loadLibrary("nfd-example");
+ }
+
+ public native static void main();
+}
diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..67d22e0
--- /dev/null
+++ b/app/src/main/jni/Android.mk
@@ -0,0 +1,8 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := nfd-example
+LOCAL_SRC_FILES := android-logger-streambuf.cpp wrappers-example.cpp
+# LOCAL_SHARED_LIBRARIES :=
+LOCAL_LDLIBS := -llog
+include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk
new file mode 100644
index 0000000..980d621
--- /dev/null
+++ b/app/src/main/jni/Application.mk
@@ -0,0 +1,5 @@
+APP_ABI=all
+
+APP_STL := gnustl_shared
+APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti
+
diff --git a/app/src/main/jni/android-logger-streambuf.cpp b/app/src/main/jni/android-logger-streambuf.cpp
new file mode 100644
index 0000000..f693501
--- /dev/null
+++ b/app/src/main/jni/android-logger-streambuf.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "android-logger-streambuf.hpp"
+
+#include <android/log.h>
+
+namespace nfd_android {
+
+AndroidLoggerStreambuf::AndroidLoggerStreambuf()
+{
+ this->setp(buffer, buffer + MAX_BUF_SIZE - 1);
+}
+
+int
+AndroidLoggerStreambuf::overflow(int c)
+{
+ if (c == traits_type::eof()) {
+ *this->pptr() = traits_type::to_char_type(c);
+ this->sbumpc();
+ }
+ return this->sync()? traits_type::eof(): traits_type::not_eof(c);
+}
+
+int
+AndroidLoggerStreambuf::sync()
+{
+ int rc = 0;
+ if (this->pbase() != this->pptr()) {
+ __android_log_print(ANDROID_LOG_INFO, "Native", "%s",
+ std::string(this->pbase(), this->pptr() - this->pbase()).c_str());
+ rc = 0;
+ this->setp(buffer, buffer + MAX_BUF_SIZE - 1);
+ }
+ return rc;
+}
+
+} // namespace nfd_android
diff --git a/app/src/main/jni/android-logger-streambuf.hpp b/app/src/main/jni/android-logger-streambuf.hpp
new file mode 100644
index 0000000..6ca2500
--- /dev/null
+++ b/app/src/main/jni/android-logger-streambuf.hpp
@@ -0,0 +1,57 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_ANDROID_JNI_ANDROID_LOG_HPP
+#define NFD_ANDROID_JNI_ANDROID_LOG_HPP
+
+#include <streambuf>
+
+namespace nfd_android {
+
+/**
+ * @brief Streambuf implementation to redirect to streams to Android logging facility
+ *
+ * Based on code from http://stackoverflow.com/a/8870278/2150331
+ */
+class AndroidLoggerStreambuf : public std::streambuf
+{
+public:
+ AndroidLoggerStreambuf();
+
+protected:
+ virtual int
+ overflow(int c);
+
+ virtual int
+ sync();
+
+private:
+ enum { MAX_BUF_SIZE = 1024 };
+ char buffer[MAX_BUF_SIZE];
+};
+
+} // namespace nfd_android
+
+#endif // NFD_ANDROID_JNI_ANDROID_LOG_HPP
diff --git a/app/src/main/jni/wrappers-example.cpp b/app/src/main/jni/wrappers-example.cpp
new file mode 100644
index 0000000..5553258
--- /dev/null
+++ b/app/src/main/jni/wrappers-example.cpp
@@ -0,0 +1,43 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "wrappers-example.hpp"
+#include "android-logger-streambuf.hpp"
+
+#include <iostream>
+
+JNIEXPORT void JNICALL
+Java_net_named_1data_nfd_wrappers_Example_main(JNIEnv*, jclass)
+{
+ nfd_android::AndroidLoggerStreambuf newBuffer;
+ std::streambuf *backupCout = std::cout.rdbuf(&newBuffer);
+ std::streambuf *backupCerr = std::cerr.rdbuf(&newBuffer);
+
+ std::cout << "Test message to cout" << std::endl;
+ std::cerr << "Test message to cerr" << std::endl;
+
+ std::cerr.rdbuf(backupCerr);
+ std::cout.rdbuf(backupCout);
+}
diff --git a/app/src/main/jni/wrappers-example.hpp b/app/src/main/jni/wrappers-example.hpp
new file mode 100644
index 0000000..9bf11e3
--- /dev/null
+++ b/app/src/main/jni/wrappers-example.hpp
@@ -0,0 +1,46 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class net_named_data_nfd_wrappers_Example */
+
+#ifndef _Included_net_named_data_nfd_wrappers_Example
+#define _Included_net_named_data_nfd_wrappers_Example
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: net_named_data_nfd_wrappers_Example
+ * Method: main
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_net_named_1data_nfd_wrappers_Example_main
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4df1894
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..63746a1
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">NFD</string>
+</resources>
diff --git a/app/src/main/res/values/strings_activity_nfd_settings.xml b/app/src/main/res/values/strings_activity_nfd_settings.xml
new file mode 100644
index 0000000..2686b04
--- /dev/null
+++ b/app/src/main/res/values/strings_activity_nfd_settings.xml
@@ -0,0 +1,60 @@
+<resources>
+
+ <!-- Strings related to Settings -->
+
+ <!-- Example General settings -->
+ <string name="pref_header_general">General</string>
+
+ <string name="pref_title_social_recommendations">Enable social recommendations</string>
+ <string name="pref_description_social_recommendations">Recommendations for people to contact
+ based on your message history
+ </string>
+
+ <string name="pref_title_display_name">Display name</string>
+ <string name="pref_default_display_name">John Smith</string>
+
+ <string name="pref_title_add_friends_to_messages">Add friends to messages</string>
+ <string-array name="pref_example_list_titles">
+ <item>Always</item>
+ <item>When possible</item>
+ <item>Never</item>
+ </string-array>
+ <string-array name="pref_example_list_values">
+ <item>1</item>
+ <item>0</item>
+ <item>-1</item>
+ </string-array>
+
+ <!-- Example settings for Data & Sync -->
+ <string name="pref_header_data_sync">Data & sync</string>
+
+ <string name="pref_title_sync_frequency">Sync frequency</string>
+ <string-array name="pref_sync_frequency_titles">
+ <item>15 minutes</item>
+ <item>30 minutes</item>
+ <item>1 hour</item>
+ <item>3 hours</item>
+ <item>6 hours</item>
+ <item>Never</item>
+ </string-array>
+ <string-array name="pref_sync_frequency_values">
+ <item>15</item>
+ <item>30</item>
+ <item>60</item>
+ <item>180</item>
+ <item>360</item>
+ <item>-1</item>
+ </string-array>
+
+ <string name="pref_title_system_sync_settings">System sync settings</string>
+
+ <!-- Example settings for Notifications -->
+ <string name="pref_header_notifications">Notifications</string>
+
+ <string name="pref_title_new_message_notifications">New message notifications</string>
+
+ <string name="pref_title_ringtone">Ringtone</string>
+ <string name="pref_ringtone_silent">Silent</string>
+
+ <string name="pref_title_vibrate">Vibrate</string>
+</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..766ab99
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ </style>
+
+</resources>
diff --git a/app/src/main/res/xml/pref_data_sync.xml b/app/src/main/res/xml/pref_data_sync.xml
new file mode 100644
index 0000000..ffda831
--- /dev/null
+++ b/app/src/main/res/xml/pref_data_sync.xml
@@ -0,0 +1,21 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
+ dismiss it. -->
+ <!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
+ <ListPreference
+ android:key="sync_frequency"
+ android:title="@string/pref_title_sync_frequency"
+ android:entries="@array/pref_sync_frequency_titles"
+ android:entryValues="@array/pref_sync_frequency_values"
+ android:defaultValue="180"
+ android:negativeButtonText="@null"
+ android:positiveButtonText="@null" />
+
+ <!-- This preference simply launches an intent when selected. Use this UI sparingly, per
+ design guidelines. -->
+ <Preference android:title="@string/pref_title_system_sync_settings">
+ <intent android:action="android.settings.SYNC_SETTINGS" />
+ </Preference>
+
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml
new file mode 100644
index 0000000..c49cbed
--- /dev/null
+++ b/app/src/main/res/xml/pref_general.xml
@@ -0,0 +1,33 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <CheckBoxPreference
+ android:key="example_checkbox"
+ android:title="@string/pref_title_social_recommendations"
+ android:summary="@string/pref_description_social_recommendations"
+ android:defaultValue="true" />
+
+ <!-- NOTE: EditTextPreference accepts EditText attributes. -->
+ <!-- NOTE: EditTextPreference's summary should be set to its value by the activity code. -->
+ <EditTextPreference
+ android:key="example_text"
+ android:title="@string/pref_title_display_name"
+ android:defaultValue="@string/pref_default_display_name"
+ android:selectAllOnFocus="true"
+ android:inputType="textCapWords"
+ android:capitalize="words"
+ android:singleLine="true"
+ android:maxLines="1" />
+
+ <!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
+ dismiss it. -->
+ <!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
+ <ListPreference
+ android:key="example_list"
+ android:title="@string/pref_title_add_friends_to_messages"
+ android:defaultValue="-1"
+ android:entries="@array/pref_example_list_titles"
+ android:entryValues="@array/pref_example_list_values"
+ android:negativeButtonText="@null"
+ android:positiveButtonText="@null" />
+
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/pref_headers.xml b/app/src/main/res/xml/pref_headers.xml
new file mode 100644
index 0000000..f2af3f2
--- /dev/null
+++ b/app/src/main/res/xml/pref_headers.xml
@@ -0,0 +1,17 @@
+<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- These settings headers are only used on tablets. -->
+
+ <header
+ android:fragment="nfd.named_data.net.nfd.NfdSettingsActivity$GeneralPreferenceFragment"
+ android:title="@string/pref_header_general"/>
+
+ <header
+ android:fragment="nfd.named_data.net.nfd.NfdSettingsActivity$NotificationPreferenceFragment"
+ android:title="@string/pref_header_notifications"/>
+
+ <header
+ android:fragment="nfd.named_data.net.nfd.NfdSettingsActivity$DataSyncPreferenceFragment"
+ android:title="@string/pref_header_data_sync"/>
+
+</preference-headers>
diff --git a/app/src/main/res/xml/pref_notification.xml b/app/src/main/res/xml/pref_notification.xml
new file mode 100644
index 0000000..b4b8cae
--- /dev/null
+++ b/app/src/main/res/xml/pref_notification.xml
@@ -0,0 +1,27 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- A 'parent' preference, which enables/disables child preferences (below)
+ when checked/unchecked. -->
+ <CheckBoxPreference
+ android:key="notifications_new_message"
+ android:title="@string/pref_title_new_message_notifications"
+ android:defaultValue="true" />
+
+ <!-- Allows the user to choose a ringtone in the 'notification' category. -->
+ <!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
+ <!-- NOTE: RingtonePreference's summary should be set to its value by the activity code. -->
+ <RingtonePreference
+ android:dependency="notifications_new_message"
+ android:key="notifications_new_message_ringtone"
+ android:title="@string/pref_title_ringtone"
+ android:ringtoneType="notification"
+ android:defaultValue="content://settings/system/notification_sound" />
+
+ <!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
+ <CheckBoxPreference
+ android:dependency="notifications_new_message"
+ android:key="notifications_new_message_vibrate"
+ android:title="@string/pref_title_vibrate"
+ android:defaultValue="true" />
+
+</PreferenceScreen>