New hidden services management screen and database
This commit is contained in:
parent
84d6a767ae
commit
26d938126f
|
@ -28,7 +28,8 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':orbotservice')
|
compile project(':orbotservice')
|
||||||
|
|
||||||
compile 'com.android.support:support-v4:23.4.0'
|
compile 'com.android.support:support-v4:23.4.0'
|
||||||
compile 'com.android.support:appcompat-v7:23.4.0'
|
compile 'com.android.support:appcompat-v7:23.4.0'
|
||||||
|
compile 'com.android.support:design:23.4.0'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.torproject.android"
|
package="org.torproject.android"
|
||||||
android:versionName="15.2.0-RC-8-multi"
|
|
||||||
android:versionCode="15208000"
|
|
||||||
android:installLocation="auto"
|
android:installLocation="auto"
|
||||||
>
|
android:versionCode="15208000"
|
||||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23"/>
|
android:versionName="15.2.0-RC-8-multi">
|
||||||
|
|
||||||
|
<uses-sdk
|
||||||
|
android:minSdkVersion="16"
|
||||||
|
android:targetSdkVersion="23" />
|
||||||
<!--
|
<!--
|
||||||
<permission android:name="org.torproject.android.MANAGE_TOR"
|
<permission android:name="org.torproject.android.MANAGE_TOR"
|
||||||
android:label="@string/permission_manage_tor_label"
|
android:label="@string/permission_manage_tor_label"
|
||||||
|
@ -20,84 +22,83 @@
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
|
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
|
||||||
|
|
||||||
<application android:name="org.torproject.android.OrbotApp" android:icon="@drawable/ic_launcher"
|
<android:uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
android:label="@string/app_name"
|
<android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
android:description="@string/app_description"
|
<android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
android:configChanges="locale|orientation|screenSize"
|
|
||||||
android:theme="@style/DefaultTheme"
|
<application
|
||||||
|
android:name=".OrbotApp"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:allowClearUserData="true"
|
android:allowClearUserData="true"
|
||||||
android:largeHeap="false"
|
android:configChanges="locale|orientation|screenSize"
|
||||||
|
android:description="@string/app_description"
|
||||||
android:hardwareAccelerated="false"
|
android:hardwareAccelerated="false"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
>
|
android:label="@string/app_name"
|
||||||
|
android:largeHeap="false"
|
||||||
<activity android:name=".OrbotMainActivity"
|
android:theme="@style/DefaultTheme">
|
||||||
|
<activity
|
||||||
|
android:name=".OrbotMainActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop">
|
||||||
>
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
<data android:scheme="bridge" />
|
<data android:scheme="bridge" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
|
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<action android:name="org.torproject.android.START_TOR" />
|
<action android:name="org.torproject.android.START_TOR" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<!--
|
<!-- This is for ensuring the background service still runs when/if the app is swiped away -->
|
||||||
This is for ensuring the background service still runs when/if the app is swiped away
|
|
||||||
-->
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".service.util.DummyActivity"
|
android:name=".service.util.DummyActivity"
|
||||||
android:theme="@android:style/Theme.Translucent"
|
|
||||||
android:enabled="true"
|
|
||||||
android:allowTaskReparenting="true"
|
android:allowTaskReparenting="true"
|
||||||
android:noHistory="true"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:alwaysRetainTaskState="false"
|
android:alwaysRetainTaskState="false"
|
||||||
android:stateNotNeeded="true"
|
|
||||||
android:clearTaskOnLaunch="true"
|
android:clearTaskOnLaunch="true"
|
||||||
|
android:enabled="true"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
android:finishOnTaskLaunch="true"
|
android:finishOnTaskLaunch="true"
|
||||||
|
android:noHistory="true"
|
||||||
/>
|
android:stateNotNeeded="true"
|
||||||
|
android:theme="@android:style/Theme.Translucent" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".vpn.VPNEnableActivity" android:label="@string/app_name" android:exported="false"
|
android:name=".vpn.VPNEnableActivity"
|
||||||
/>
|
android:exported="false"
|
||||||
|
android:label="@string/app_name" />
|
||||||
|
<activity
|
||||||
<activity android:name="org.torproject.android.ui.PromoAppsActivity" android:exported="false"/>
|
android:name=".ui.PromoAppsActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
<activity android:name=".settings.SettingsPreferences" android:label="@string/app_name"/>
|
android:name=".settings.SettingsPreferences"
|
||||||
<activity android:name=".ui.AppManager" android:label="@string/app_name"
|
android:label="@string/app_name" />
|
||||||
android:theme="@style/Theme.AppCompat"
|
<activity
|
||||||
/>
|
android:name=".ui.AppManager"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/Theme.AppCompat" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.TorService"
|
android:name=".service.TorService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||||
android:stopWithTask="false" >
|
android:stopWithTask="false" />
|
||||||
</service>
|
|
||||||
|
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.vpn.TorVpnService"
|
android:name=".service.vpn.TorVpnService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
|
@ -114,24 +115,36 @@
|
||||||
<action android:name="org.torproject.android.intent.action.START" />
|
<action android:name="org.torproject.android.intent.action.START" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
<receiver
|
||||||
<receiver android:name=".OnBootReceiver"
|
android:name=".OnBootReceiver"
|
||||||
android:enabled="true" android:exported="true"
|
android:enabled="true"
|
||||||
|
android:exported="true">
|
||||||
>
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.HOME" />
|
<category android:name="android.intent.category.HOME" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.HOME" />
|
<category android:name="android.intent.category.HOME" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MEDIA_MOUNTED" />
|
<action android:name="android.intent.action.MEDIA_MOUNTED" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.HOME" />
|
<category android:name="android.intent.category.HOME" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".ui.hs.HiddenServicesActivity"
|
||||||
|
android:label="@string/title_activity_hidden_services"
|
||||||
|
android:theme="@style/DefaultTheme" />
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name=".ui.hs.providers.HSContentProvider"
|
||||||
|
android:exported="false"
|
||||||
|
android:authorities="org.torproject.android.ui.hs.providers" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -23,6 +23,7 @@ import org.torproject.android.service.TorServiceConstants;
|
||||||
import org.torproject.android.service.util.TorServiceUtils;
|
import org.torproject.android.service.util.TorServiceUtils;
|
||||||
import org.torproject.android.settings.SettingsPreferences;
|
import org.torproject.android.settings.SettingsPreferences;
|
||||||
import org.torproject.android.ui.AppManager;
|
import org.torproject.android.ui.AppManager;
|
||||||
|
import org.torproject.android.ui.hs.HiddenServicesActivity;
|
||||||
import org.torproject.android.ui.ImageProgressView;
|
import org.torproject.android.ui.ImageProgressView;
|
||||||
import org.torproject.android.ui.PromoAppsActivity;
|
import org.torproject.android.ui.PromoAppsActivity;
|
||||||
import org.torproject.android.ui.Rotate3dAnimation;
|
import org.torproject.android.ui.Rotate3dAnimation;
|
||||||
|
@ -478,6 +479,10 @@ public class OrbotMainActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (item.getItemId() == R.id.menu_hidden_services)
|
||||||
|
{
|
||||||
|
startActivity(new Intent(this, HiddenServicesActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
|
|
|
@ -37,9 +37,6 @@ public class SettingsPreferences
|
||||||
private Preference prefTransProxyFlush = null;
|
private Preference prefTransProxyFlush = null;
|
||||||
|
|
||||||
private Preference prefTransProxyApps = null;
|
private Preference prefTransProxyApps = null;
|
||||||
private CheckBoxPreference prefHiddenServices = null;
|
|
||||||
private EditTextPreference prefHiddenServicesPorts;
|
|
||||||
private EditTextPreference prefHiddenServicesHostname;
|
|
||||||
private CheckBoxPreference prefRequestRoot = null;
|
private CheckBoxPreference prefRequestRoot = null;
|
||||||
private ListPreference prefLocale = null;
|
private ListPreference prefLocale = null;
|
||||||
|
|
||||||
|
@ -104,10 +101,6 @@ public class SettingsPreferences
|
||||||
prefTransProxyApps.setOnPreferenceClickListener(this);
|
prefTransProxyApps.setOnPreferenceClickListener(this);
|
||||||
prefCBTransProxy.setOnPreferenceClickListener(this);
|
prefCBTransProxy.setOnPreferenceClickListener(this);
|
||||||
prefcBTransProxyAll.setOnPreferenceClickListener(this);
|
prefcBTransProxyAll.setOnPreferenceClickListener(this);
|
||||||
prefHiddenServices = (CheckBoxPreference) findPreference("pref_hs_enable");
|
|
||||||
prefHiddenServices.setOnPreferenceClickListener(this);
|
|
||||||
prefHiddenServicesHostname = (EditTextPreference) findPreference("pref_hs_hostname");
|
|
||||||
|
|
||||||
|
|
||||||
prefCBTransProxy.setEnabled(prefRequestRoot.isChecked());
|
prefCBTransProxy.setEnabled(prefRequestRoot.isChecked());
|
||||||
prefcBTransProxyAll.setEnabled(prefCBTransProxy.isChecked());
|
prefcBTransProxyAll.setEnabled(prefCBTransProxy.isChecked());
|
||||||
|
@ -116,10 +109,6 @@ public class SettingsPreferences
|
||||||
if (prefCBTransProxy.isChecked())
|
if (prefCBTransProxy.isChecked())
|
||||||
prefTransProxyApps.setEnabled((!prefcBTransProxyAll.isChecked()));
|
prefTransProxyApps.setEnabled((!prefcBTransProxyAll.isChecked()));
|
||||||
|
|
||||||
prefHiddenServicesPorts = (EditTextPreference) findPreference("pref_hs_ports");
|
|
||||||
prefHiddenServicesHostname.setEnabled(prefHiddenServices.isChecked());
|
|
||||||
prefHiddenServicesPorts.setEnabled(prefHiddenServices.isChecked());
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||||
{
|
{
|
||||||
prefTransProxyApps.setEnabled(true);
|
prefTransProxyApps.setEnabled(true);
|
||||||
|
@ -153,11 +142,6 @@ public class SettingsPreferences
|
||||||
{
|
{
|
||||||
startActivity(new Intent(this, AppManager.class));
|
startActivity(new Intent(this, AppManager.class));
|
||||||
|
|
||||||
}
|
|
||||||
else if (preference == prefHiddenServices)
|
|
||||||
{
|
|
||||||
prefHiddenServicesPorts.setEnabled(prefHiddenServices.isChecked());
|
|
||||||
prefHiddenServicesHostname.setEnabled(prefHiddenServices.isChecked());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package org.torproject.android.ui.hs;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.support.design.widget.FloatingActionButton;
|
||||||
|
import android.support.design.widget.Snackbar;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.torproject.android.R;
|
||||||
|
import org.torproject.android.ui.hs.adapters.HSAdapter;
|
||||||
|
import org.torproject.android.ui.hs.providers.HSContentProvider;
|
||||||
|
|
||||||
|
public class HiddenServicesActivity extends AppCompatActivity {
|
||||||
|
private HSAdapter mHiddenServices;
|
||||||
|
private ContentResolver mCR;
|
||||||
|
private HSObserver mHSObserver;
|
||||||
|
private String[] mProjection = new String[]{
|
||||||
|
HSContentProvider.HiddenService._ID,
|
||||||
|
HSContentProvider.HiddenService.NAME,
|
||||||
|
HSContentProvider.HiddenService.DOMAIN,
|
||||||
|
HSContentProvider.HiddenService.PORT};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_hidden_services);
|
||||||
|
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
|
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
|
||||||
|
fab.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||||
|
.setAction("Action", null).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mCR = getContentResolver();
|
||||||
|
// View adapter
|
||||||
|
mHiddenServices = new HSAdapter(
|
||||||
|
mCR.query(
|
||||||
|
HSContentProvider.CONTENT_URI, mProjection, null, null, null
|
||||||
|
));
|
||||||
|
|
||||||
|
mHSObserver = new HSObserver(new Handler());
|
||||||
|
mCR.registerContentObserver(HSContentProvider.CONTENT_URI, true, mHSObserver);
|
||||||
|
|
||||||
|
// Fill view
|
||||||
|
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.onion_list);
|
||||||
|
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
|
mRecyclerView.setAdapter(mHiddenServices);
|
||||||
|
}
|
||||||
|
|
||||||
|
class HSObserver extends ContentObserver {
|
||||||
|
public HSObserver(Handler handler) {
|
||||||
|
super(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange) {
|
||||||
|
// New data
|
||||||
|
mHiddenServices.changeCursor(mCR.query(
|
||||||
|
HSContentProvider.CONTENT_URI, mProjection, null, null, null
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
package org.torproject.android.ui.hs.adapters;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 skyfish.jy@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.DataSetObserver;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by skyfishjy on 10/31/14.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
|
||||||
|
|
||||||
|
private Cursor mCursor;
|
||||||
|
|
||||||
|
private boolean mDataValid;
|
||||||
|
|
||||||
|
private int mRowIdColumn;
|
||||||
|
|
||||||
|
private DataSetObserver mDataSetObserver;
|
||||||
|
|
||||||
|
public CursorRecyclerViewAdapter(Cursor cursor) {
|
||||||
|
mCursor = cursor;
|
||||||
|
mDataValid = cursor != null;
|
||||||
|
mRowIdColumn = mDataValid ? mCursor.getColumnIndex("_id") : -1;
|
||||||
|
mDataSetObserver = new NotifyingDataSetObserver();
|
||||||
|
if (mCursor != null) {
|
||||||
|
mCursor.registerDataSetObserver(mDataSetObserver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
if (mDataValid && mCursor != null) {
|
||||||
|
return mCursor.getCount();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
|
||||||
|
return mCursor.getLong(mRowIdColumn);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHasStableIds(boolean hasStableIds) {
|
||||||
|
super.setHasStableIds(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void onBindViewHolder(VH viewHolder, Cursor cursor);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(VH viewHolder, int position) {
|
||||||
|
if (!mDataValid) {
|
||||||
|
throw new IllegalStateException("this should only be called when the cursor is valid");
|
||||||
|
}
|
||||||
|
if (!mCursor.moveToPosition(position)) {
|
||||||
|
throw new IllegalStateException("couldn't move cursor to position " + position);
|
||||||
|
}
|
||||||
|
onBindViewHolder(viewHolder, mCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the underlying cursor to a new cursor. If there is an existing cursor it will be
|
||||||
|
* closed.
|
||||||
|
*/
|
||||||
|
public void changeCursor(Cursor cursor) {
|
||||||
|
Cursor old = swapCursor(cursor);
|
||||||
|
if (old != null) {
|
||||||
|
old.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeCursor() {
|
||||||
|
mCursor.unregisterDataSetObserver(mDataSetObserver);
|
||||||
|
mCursor.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap in a new Cursor, returning the old Cursor. Unlike
|
||||||
|
* {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
|
||||||
|
* closed.
|
||||||
|
*/
|
||||||
|
private Cursor swapCursor(Cursor newCursor) {
|
||||||
|
if (newCursor == mCursor) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final Cursor oldCursor = mCursor;
|
||||||
|
if (oldCursor != null && mDataSetObserver != null) {
|
||||||
|
oldCursor.unregisterDataSetObserver(mDataSetObserver);
|
||||||
|
}
|
||||||
|
mCursor = newCursor;
|
||||||
|
if (mCursor != null) {
|
||||||
|
if (mDataSetObserver != null) {
|
||||||
|
mCursor.registerDataSetObserver(mDataSetObserver);
|
||||||
|
}
|
||||||
|
mRowIdColumn = newCursor.getColumnIndexOrThrow("_id");
|
||||||
|
mDataValid = true;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
} else {
|
||||||
|
mRowIdColumn = -1;
|
||||||
|
mDataValid = false;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
|
||||||
|
}
|
||||||
|
return oldCursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NotifyingDataSetObserver extends DataSetObserver {
|
||||||
|
@Override
|
||||||
|
public void onChanged() {
|
||||||
|
super.onChanged();
|
||||||
|
mDataValid = true;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidated() {
|
||||||
|
super.onInvalidated();
|
||||||
|
mDataValid = false;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.torproject.android.ui.hs.adapters;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.torproject.android.R;
|
||||||
|
import org.torproject.android.ui.hs.providers.HSContentProvider;
|
||||||
|
|
||||||
|
public class HSAdapter extends CursorRecyclerViewAdapter<HSAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
public HSAdapter(Cursor cursor) {
|
||||||
|
super(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HSAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
View v = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.onion_item, parent, false);
|
||||||
|
|
||||||
|
ViewHolder vh = new ViewHolder(v);
|
||||||
|
|
||||||
|
return vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(ViewHolder viewHolder, Cursor cursor) {
|
||||||
|
viewHolder.id = cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService._ID));
|
||||||
|
|
||||||
|
String name_string = cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.NAME));
|
||||||
|
Integer port = cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService.PORT));
|
||||||
|
|
||||||
|
viewHolder.name.setText(name_string + ": " + port.toString());
|
||||||
|
|
||||||
|
viewHolder.domain.setText(
|
||||||
|
cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.DOMAIN))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView name;
|
||||||
|
TextView domain;
|
||||||
|
Integer id;
|
||||||
|
|
||||||
|
ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
name = (TextView) itemView.findViewById(R.id.hs_name);
|
||||||
|
domain = (TextView) itemView.findViewById(R.id.hs_onion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package org.torproject.android.ui.hs.database;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
|
public class HSDatabase extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
public static final String HS_DATA_TABLE_NAME = "hs_data";
|
||||||
|
private static final int DATABASE_VERSION = 2;
|
||||||
|
private static final String DATABASE_NAME = "hidden_services";
|
||||||
|
private static final String HS_DATA_TABLE_CREATE =
|
||||||
|
"CREATE TABLE " + HS_DATA_TABLE_NAME + " (" +
|
||||||
|
"_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||||
|
"name TEXT, " +
|
||||||
|
"domain TEXT, " +
|
||||||
|
"port INTEGER);";
|
||||||
|
|
||||||
|
public HSDatabase(Context context) {
|
||||||
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL(HS_DATA_TABLE_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
package org.torproject.android.ui.hs.providers;
|
||||||
|
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.UriMatcher;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.torproject.android.ui.hs.database.HSDatabase;
|
||||||
|
|
||||||
|
|
||||||
|
public class HSContentProvider extends ContentProvider {
|
||||||
|
private static final String AUTH = "org.torproject.android.ui.hs.providers";
|
||||||
|
public static final Uri CONTENT_URI =
|
||||||
|
Uri.parse("content://" + AUTH + "/hs");
|
||||||
|
//UriMatcher
|
||||||
|
private static final int ONIONS = 1;
|
||||||
|
private static final int ONION_ID = 2;
|
||||||
|
|
||||||
|
private static final UriMatcher uriMatcher;
|
||||||
|
|
||||||
|
//Inicializamos el UriMatcher
|
||||||
|
static {
|
||||||
|
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||||
|
uriMatcher.addURI(AUTH, "hs", ONIONS);
|
||||||
|
uriMatcher.addURI(AUTH, "hs/#", ONION_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HSDatabase mServerDB;
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
mContext = getContext();
|
||||||
|
mServerDB = new HSDatabase(mContext);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||||
|
//Si es una consulta a un ID concreto construimos el WHERE
|
||||||
|
String where = selection;
|
||||||
|
if (uriMatcher.match(uri) == ONION_ID) {
|
||||||
|
where = "_id=" + uri.getLastPathSegment();
|
||||||
|
}
|
||||||
|
|
||||||
|
SQLiteDatabase db = mServerDB.getReadableDatabase();
|
||||||
|
|
||||||
|
return db.query(HSDatabase.HS_DATA_TABLE_NAME, projection, where,
|
||||||
|
selectionArgs, null, null, sortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getType(Uri uri) {
|
||||||
|
int match = uriMatcher.match(uri);
|
||||||
|
|
||||||
|
switch (match) {
|
||||||
|
case ONIONS:
|
||||||
|
return "vnd.android.cursor.dir/vnd.torproject.onions";
|
||||||
|
case ONION_ID:
|
||||||
|
return "vnd.android.cursor.item/vnd.torproject.onion";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
long regId;
|
||||||
|
|
||||||
|
SQLiteDatabase db = mServerDB.getWritableDatabase();
|
||||||
|
|
||||||
|
regId = db.insert(HSDatabase.HS_DATA_TABLE_NAME, null, values);
|
||||||
|
|
||||||
|
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
|
||||||
|
|
||||||
|
return ContentUris.withAppendedId(CONTENT_URI, regId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||||
|
|
||||||
|
//Si es una consulta a un ID concreto construimos el WHERE
|
||||||
|
String where = selection;
|
||||||
|
if (uriMatcher.match(uri) == ONION_ID) {
|
||||||
|
where = "_id=" + uri.getLastPathSegment();
|
||||||
|
}
|
||||||
|
|
||||||
|
SQLiteDatabase db = mServerDB.getWritableDatabase();
|
||||||
|
|
||||||
|
Integer rows = db.delete(HSDatabase.HS_DATA_TABLE_NAME, where, selectionArgs);
|
||||||
|
|
||||||
|
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class HiddenService implements BaseColumns {
|
||||||
|
//Nombres de columnas
|
||||||
|
public static final String NAME = "name";
|
||||||
|
public static final String PORT = "port";
|
||||||
|
public static final String DOMAIN = "domain";
|
||||||
|
|
||||||
|
private HiddenService() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="5dp">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/hs_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/hs_onion" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
tools:context="org.torproject.android.ui.hs.HiddenServicesActivity">
|
||||||
|
|
||||||
|
<android.support.design.widget.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="@style/DefaultTheme.AppBarOverlay">
|
||||||
|
|
||||||
|
<android.support.v7.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:popupTheme="@style/DefaultTheme.PopupOverlay" />
|
||||||
|
|
||||||
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/content_hidden_services" />
|
||||||
|
|
||||||
|
<android.support.design.widget.FloatingActionButton
|
||||||
|
android:id="@+id/fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="@dimen/fab_margin"
|
||||||
|
app:srcCompat="@android:drawable/stat_notify_more" />
|
||||||
|
|
||||||
|
</android.support.design.widget.CoordinatorLayout>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/content_hidden_services"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
tools:context="org.torproject.android.ui.hs.HiddenServicesActivity"
|
||||||
|
tools:showIn="@layout/activity_hidden_services">
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/onion_list"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -44,6 +44,10 @@
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
<item android:id="@+id/menu_hidden_services"
|
||||||
|
android:title="@string/menu_hidden_services"
|
||||||
|
yourapp:showAsAction="never"
|
||||||
|
/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<item android:id="@+id/menu_promo_apps"
|
<item android:id="@+id/menu_promo_apps"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<resources></resources>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<resources>
|
||||||
|
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||||
|
(such as screen margins) for screens with more than 820dp of available width. This
|
||||||
|
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||||
|
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||||
|
</resources>
|
|
@ -1,5 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
<!--
|
|
||||||
/* //device/apps/common/assets/res/any/dimens.xml
|
/* //device/apps/common/assets/res/any/dimens.xml
|
||||||
**
|
**
|
||||||
** Copyright 2006, The Android Open Source Project
|
** Copyright 2006, The Android Open Source Project
|
||||||
|
@ -118,26 +117,27 @@
|
||||||
<!-- The platform's desired minimum size for a dialog's width when it
|
<!-- The platform's desired minimum size for a dialog's width when it
|
||||||
is along the major axis (that is the screen is landscape). This may
|
is along the major axis (that is the screen is landscape). This may
|
||||||
be either a fraction or a dimension. -->
|
be either a fraction or a dimension. -->
|
||||||
<item type="dimen" name="dialog_min_width_major">65%</item>
|
<item name="dialog_min_width_major" type="dimen">65%</item>
|
||||||
|
|
||||||
<!-- The platform's desired fixed width for a dialog along the major axis
|
<!-- The platform's desired fixed width for a dialog along the major axis
|
||||||
(the screen is in landscape). This may be either a fraction or a dimension.-->
|
(the screen is in landscape). This may be either a fraction or a dimension.-->
|
||||||
<item type="dimen" name="dialog_fixed_width_major">320dp</item>
|
<item name="dialog_fixed_width_major" type="dimen">320dp</item>
|
||||||
<!-- The platform's desired fixed width for a dialog along the minor axis
|
<!-- The platform's desired fixed width for a dialog along the minor axis
|
||||||
(the screen is in portrait). This may be either a fraction or a dimension.-->
|
(the screen is in portrait). This may be either a fraction or a dimension.-->
|
||||||
<item type="dimen" name="dialog_fixed_width_minor">320dp</item>
|
<item name="dialog_fixed_width_minor" type="dimen">320dp</item>
|
||||||
<!-- The platform's desired fixed height for a dialog along the major axis
|
<!-- The platform's desired fixed height for a dialog along the major axis
|
||||||
(the screen is in portrait). This may be either a fraction or a dimension.-->
|
(the screen is in portrait). This may be either a fraction or a dimension.-->
|
||||||
<item type="dimen" name="dialog_fixed_height_major">80%</item>
|
<item name="dialog_fixed_height_major" type="dimen">80%</item>
|
||||||
<!-- The platform's desired fixed height for a dialog along the minor axis
|
<!-- The platform's desired fixed height for a dialog along the minor axis
|
||||||
(the screen is in landscape). This may be either a fraction or a dimension.-->
|
(the screen is in landscape). This may be either a fraction or a dimension.-->
|
||||||
<item type="dimen" name="dialog_fixed_height_minor">100%</item>
|
<item name="dialog_fixed_height_minor" type="dimen">100%</item>
|
||||||
|
|
||||||
<!-- Preference activity, vertical padding for the header list -->
|
<!-- Preference activity, vertical padding for the header list -->
|
||||||
<dimen name="preference_screen_header_vertical_padding">0dp</dimen>
|
<dimen name="preference_screen_header_vertical_padding">0dp</dimen>
|
||||||
|
|
||||||
<dimen name="preference_screen_header_padding_side">16dip</dimen>
|
<dimen name="preference_screen_header_padding_side">16dip</dimen>
|
||||||
<integer name="preference_screen_header_scrollbarStyle">0x02000000</integer> <!-- outsideOverlay -->
|
<integer name="preference_screen_header_scrollbarStyle">0x02000000
|
||||||
|
</integer> <!-- outsideOverlay -->
|
||||||
|
|
||||||
<integer name="preference_fragment_scrollbarStyle">0x02000000</integer> <!-- outsideOverlay -->
|
<integer name="preference_fragment_scrollbarStyle">0x02000000</integer> <!-- outsideOverlay -->
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@
|
||||||
<!-- The platform's desired minimum size for a dialog's width when it
|
<!-- The platform's desired minimum size for a dialog's width when it
|
||||||
is along the minor axis (that is the screen is portrait). This may
|
is along the minor axis (that is the screen is portrait). This may
|
||||||
be either a fraction or a dimension. -->
|
be either a fraction or a dimension. -->
|
||||||
<item type="dimen" name="dialog_min_width_minor">95%</item>
|
<item name="dialog_min_width_minor" type="dimen">95%</item>
|
||||||
|
|
||||||
<!-- The width of the big icons in notifications. -->
|
<!-- The width of the big icons in notifications. -->
|
||||||
<dimen name="notification_large_icon_width">64dp</dimen>
|
<dimen name="notification_large_icon_width">64dp</dimen>
|
||||||
|
@ -358,4 +358,8 @@
|
||||||
|
|
||||||
<!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
|
<!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
|
||||||
<dimen name="immersive_mode_cling_width">-1px</dimen>
|
<dimen name="immersive_mode_cling_width">-1px</dimen>
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
<dimen name="fab_margin">16dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -89,7 +89,6 @@
|
||||||
<!--END Welcome Wizard strings (DJH)-->
|
<!--END Welcome Wizard strings (DJH)-->
|
||||||
<string name="connect_first_time">You\'ve successfully connected to the Tor network - but this does NOT mean your device is secure. You can use the \'Browser\' button to test your connection. \n\nVisit us at https://guardianproject.info/apps/orbot or send an email to help@guardianproject.info to learn more.</string>
|
<string name="connect_first_time">You\'ve successfully connected to the Tor network - but this does NOT mean your device is secure. You can use the \'Browser\' button to test your connection. \n\nVisit us at https://guardianproject.info/apps/orbot or send an email to help@guardianproject.info to learn more.</string>
|
||||||
<string name="tor_check">This will open your web browser to https://check.torproject.org in order to see if Orbot is probably configured and you are connected to Tor.</string>
|
<string name="tor_check">This will open your web browser to https://check.torproject.org in order to see if Orbot is probably configured and you are connected to Tor.</string>
|
||||||
<string name="pref_hs_group">Hidden Service Hosting</string>
|
|
||||||
<string name="pref_general_group">General</string>
|
<string name="pref_general_group">General</string>
|
||||||
<string name="pref_start_boot_title">Start Orbot on Boot</string>
|
<string name="pref_start_boot_title">Start Orbot on Boot</string>
|
||||||
<string name="pref_start_boot_summary">Automatically start Orbot and connect Tor when your Android device boots</string>
|
<string name="pref_start_boot_summary">Automatically start Orbot and connect Tor when your Android device boots</string>
|
||||||
|
@ -156,7 +155,6 @@
|
||||||
<string name="pref_proxy_password_dialog">Enter Proxy Password</string>
|
<string name="pref_proxy_password_dialog">Enter Proxy Password</string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<string name="status">Status</string>
|
<string name="status">Status</string>
|
||||||
<string name="setting_up_full_transparent_proxying_">Setting up full transparent proxying…</string>
|
<string name="setting_up_full_transparent_proxying_">Setting up full transparent proxying…</string>
|
||||||
<string name="setting_up_app_based_transparent_proxying_">Setting up app-based transparent proxying…</string>
|
<string name="setting_up_app_based_transparent_proxying_">Setting up app-based transparent proxying…</string>
|
||||||
|
@ -202,11 +200,7 @@
|
||||||
<string name="reachable_ports">Reachable ports</string>
|
<string name="reachable_ports">Reachable ports</string>
|
||||||
<string name="ports_reachable_behind_a_restrictive_firewall">Ports reachable behind a restrictive firewall</string>
|
<string name="ports_reachable_behind_a_restrictive_firewall">Ports reachable behind a restrictive firewall</string>
|
||||||
<string name="enter_ports">Enter ports</string>
|
<string name="enter_ports">Enter ports</string>
|
||||||
<string name="enable_hidden_services">Hidden Service Hosting</string>
|
<string name="menu_hidden_services">Hidden Services</string>
|
||||||
<string name="run_servers_accessible_via_the_tor_network">allow on-device server to be accessible via the Tor network</string>
|
|
||||||
<string name="enter_localhost_ports_for_hidden_services">enter localhost ports for hidden services</string>
|
|
||||||
<string name="hidden_service_ports">Hidden Service Ports</string>
|
|
||||||
<string name="the_addressable_name_for_your_hidden_service_generated_automatically_">the addressable name for your hidden service (generated automatically)</string>
|
|
||||||
<string name="enable_debug_log_to_output_must_use_adb_or_alogcat_to_view_">enable debug log to output (must use adb or aLogCat to view)</string>
|
<string name="enable_debug_log_to_output_must_use_adb_or_alogcat_to_view_">enable debug log to output (must use adb or aLogCat to view)</string>
|
||||||
<string name="project_home">Project Home(s): </string>
|
<string name="project_home">Project Home(s): </string>
|
||||||
<string name="project_urls">https://www.torproject.org/docs/android\nhttps://guardianproject.info/apps/orbot/</string>
|
<string name="project_urls">https://www.torproject.org/docs/android\nhttps://guardianproject.info/apps/orbot/</string>
|
||||||
|
@ -336,4 +330,5 @@
|
||||||
<string name="note_only_standard_tor_bridges_work_on_intel_x86_atom_devices">NOTE: Only standard Tor bridges work on Intel X86/ATOM devices</string>
|
<string name="note_only_standard_tor_bridges_work_on_intel_x86_atom_devices">NOTE: Only standard Tor bridges work on Intel X86/ATOM devices</string>
|
||||||
|
|
||||||
<string name="vpn_default_world">World (Location)</string>
|
<string name="vpn_default_world">World (Location)</string>
|
||||||
|
<string name="title_activity_hidden_services">Hidden Services</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" />
|
<style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" />
|
||||||
|
|
||||||
<style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />
|
<style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />
|
||||||
|
|
||||||
|
<style name="DefaultTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||||
|
|
||||||
|
<style name="DefaultTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -157,17 +157,6 @@ android:dialogTitle="@string/enter_ports"
|
||||||
/>
|
/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/pref_hs_group">
|
|
||||||
<CheckBoxPreference android:title="@string/enable_hidden_services"
|
|
||||||
android:summary="@string/run_servers_accessible_via_the_tor_network" android:key="pref_hs_enable"></CheckBoxPreference>
|
|
||||||
<EditTextPreference android:summary="@string/enter_localhost_ports_for_hidden_services"
|
|
||||||
android:title="@string/hidden_service_ports" android:enabled="false" android:key="pref_hs_ports"></EditTextPreference>
|
|
||||||
|
|
||||||
<EditTextPreference android:key="pref_hs_hostname"
|
|
||||||
android:summary="@string/the_addressable_name_for_your_hidden_service_generated_automatically_"
|
|
||||||
android:title=".Onion Hostname"></EditTextPreference>
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/pref_proxy_title">
|
<PreferenceCategory android:title="@string/pref_proxy_title">
|
||||||
<EditTextPreference android:key="pref_proxy_type"
|
<EditTextPreference android:key="pref_proxy_type"
|
||||||
android:title="@string/pref_proxy_type_title"
|
android:title="@string/pref_proxy_type_title"
|
||||||
|
|
Loading…
Reference in New Issue