Better connection handling and initial code for settings activity
This commit is contained in:
@@ -21,9 +21,11 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'com.android.support:support-v4:27.0.2'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
||||
def supportLibVersion = "27.0.2"
|
||||
implementation "com.android.support:appcompat-v7:$supportLibVersion"
|
||||
implementation "com.android.support:support-v4:$supportLibVersion"
|
||||
implementation 'com.android.support:design:27.0.2'
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.rumpold.androiddsky">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
@@ -14,12 +16,15 @@
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/FullscreenTheme">
|
||||
<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>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.SettingsActivity"
|
||||
android:label="@string/title_activity_settings">
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
@@ -1,9 +1,13 @@
|
||||
package de.rumpold.androiddsky;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -72,7 +76,18 @@ public class DSKY {
|
||||
|
||||
public DSKY(DSKYActivity activity) {
|
||||
this.activity = activity;
|
||||
this.client = new YaAgcClient(this);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext());
|
||||
final String agcHost = preferences.getString("agc_host", null);
|
||||
final int agcPort = Integer.parseInt(preferences.getString("agc_port", "-1"));
|
||||
|
||||
if (agcHost == null || agcPort <= 0) {
|
||||
this.client = null;
|
||||
return;
|
||||
} else {
|
||||
final SocketAddress agcAddress = new InetSocketAddress(agcHost, agcPort);
|
||||
this.client = new YaAgcClient(this, agcAddress);
|
||||
}
|
||||
|
||||
Arrays.fill(register1, ' ');
|
||||
Arrays.fill(register2, ' ');
|
||||
@@ -88,9 +103,11 @@ public class DSKY {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (client != null) {
|
||||
client.connect();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Cannot connect to yaAGC", e);
|
||||
// throw new RuntimeException("Cannot connect to yaAGC", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -134,7 +151,9 @@ public class DSKY {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (client != null) {
|
||||
client.disconnect();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Cannot connect to yaAGC", e);
|
||||
}
|
||||
@@ -253,6 +272,9 @@ public class DSKY {
|
||||
|
||||
public void buttonPressed(final String button) {
|
||||
Log.d(TAG, "buttonPressed: " + button);
|
||||
if (client == null) {
|
||||
return;
|
||||
}
|
||||
AsyncTask.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -265,4 +287,8 @@ public class DSKY {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return client != null && client.isConnected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package de.rumpold.androiddsky.network;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedByInterruptException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import de.rumpold.androiddsky.DSKY;
|
||||
@@ -15,13 +18,12 @@ import de.rumpold.androiddsky.DSKY;
|
||||
*/
|
||||
@SuppressWarnings("OctalInteger")
|
||||
public class YaAgcClient {
|
||||
private static final String YAAGC_HOST = "192.168.178.29";
|
||||
private static final int YAAGC_SERVER_PORT = 19697;
|
||||
private static final String TAG = YaAgcClient.class.getSimpleName();
|
||||
|
||||
private static final int KEYBOARD_CHANNEL = 015;
|
||||
|
||||
private final DSKY dsky;
|
||||
private final SocketAddress agcAddress;
|
||||
private SocketChannel agcChannel;
|
||||
private Thread handler;
|
||||
|
||||
@@ -54,23 +56,31 @@ public class YaAgcClient {
|
||||
|
||||
buf.position(buf.position() + 4);
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
} catch (ClosedByInterruptException | InterruptedException ignored) {
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Connection error", e);
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(dsky.getActivity().getApplicationContext(),
|
||||
"Connection failure",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
Log.w(TAG, "Connection error", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public YaAgcClient(DSKY dsky) {
|
||||
public YaAgcClient(DSKY dsky, SocketAddress agcAddress) {
|
||||
this.dsky = dsky;
|
||||
this.agcAddress = agcAddress;
|
||||
}
|
||||
|
||||
public void connect() throws IOException {
|
||||
Log.i(TAG, "Connecting to yaAGC at " + agcAddress);
|
||||
agcChannel = SocketChannel.open();
|
||||
boolean success = agcChannel.connect(new InetSocketAddress(YAAGC_HOST, YAAGC_SERVER_PORT));
|
||||
boolean success = agcChannel.connect(agcAddress);
|
||||
|
||||
if (success) {
|
||||
Log.i(TAG, "connect: Successfully connected, starting DSKY I/O handler");
|
||||
@@ -80,6 +90,7 @@ public class YaAgcClient {
|
||||
}
|
||||
|
||||
public void disconnect() throws IOException {
|
||||
Log.i(TAG, "Disconnecting from AGC");
|
||||
if (handler != null) {
|
||||
handler.interrupt();
|
||||
try {
|
||||
@@ -91,6 +102,10 @@ public class YaAgcClient {
|
||||
agcChannel.close();
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return agcChannel.isConnected();
|
||||
}
|
||||
|
||||
public void sendKeyCode(int keyCode) throws IOException {
|
||||
sendChannelOutput(KEYBOARD_CHANNEL, keyCode);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package de.rumpold.androiddsky.ui;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatDelegate;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
|
||||
* to be used with AppCompat.
|
||||
*/
|
||||
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
|
||||
|
||||
private AppCompatDelegate mDelegate;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
getDelegate().installViewFactory();
|
||||
getDelegate().onCreate(savedInstanceState);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
getDelegate().onPostCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
public ActionBar getSupportActionBar() {
|
||||
return getDelegate().getSupportActionBar();
|
||||
}
|
||||
|
||||
public void setSupportActionBar(@Nullable Toolbar toolbar) {
|
||||
getDelegate().setSupportActionBar(toolbar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuInflater getMenuInflater() {
|
||||
return getDelegate().getMenuInflater();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(@LayoutRes int layoutResID) {
|
||||
getDelegate().setContentView(layoutResID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view) {
|
||||
getDelegate().setContentView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params) {
|
||||
getDelegate().setContentView(view, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContentView(View view, ViewGroup.LayoutParams params) {
|
||||
getDelegate().addContentView(view, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostResume() {
|
||||
super.onPostResume();
|
||||
getDelegate().onPostResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTitleChanged(CharSequence title, int color) {
|
||||
super.onTitleChanged(title, color);
|
||||
getDelegate().setTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
getDelegate().onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
getDelegate().onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
getDelegate().onDestroy();
|
||||
}
|
||||
|
||||
public void invalidateOptionsMenu() {
|
||||
getDelegate().invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private AppCompatDelegate getDelegate() {
|
||||
if (mDelegate == null) {
|
||||
mDelegate = AppCompatDelegate.create(this, null);
|
||||
}
|
||||
return mDelegate;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
package de.rumpold.androiddsky.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
@@ -25,7 +29,7 @@ public class DSKYActivity extends AppCompatActivity {
|
||||
|
||||
private final Handler mViewHandler = new Handler();
|
||||
|
||||
private final DSKY dsky = new DSKY(this);
|
||||
private DSKY dsky;
|
||||
private int rightActiveColor;
|
||||
private int activeColor;
|
||||
private int passiveColor;
|
||||
@@ -73,6 +77,8 @@ public class DSKYActivity extends AppCompatActivity {
|
||||
|
||||
setContentView(R.layout.activity_dsky);
|
||||
|
||||
dsky = new DSKY(this);
|
||||
|
||||
// Colors
|
||||
rightActiveColor = getResources().getColor(R.color.indicatorRightActive);
|
||||
activeColor = getResources().getColor(R.color.indicatorActive);
|
||||
@@ -82,6 +88,33 @@ public class DSKYActivity extends AppCompatActivity {
|
||||
createButtonListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_connect:
|
||||
if (!dsky.isConnected()) {
|
||||
dsky.connect();
|
||||
} else {
|
||||
dsky.disconnect();
|
||||
}
|
||||
return true;
|
||||
|
||||
case R.id.action_settings:
|
||||
final Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.dsky_menu, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
private void createButtonListeners() {
|
||||
final View.OnClickListener buttonListener = new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -117,12 +150,17 @@ public class DSKYActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
final boolean autoConnect = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("auto_connect", false);
|
||||
if (autoConnect) {
|
||||
dsky.connect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (dsky.isConnected()) {
|
||||
dsky.disconnect();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
package de.rumpold.androiddsky.ui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
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.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.RingtonePreference;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.rumpold.androiddsky.R;
|
||||
|
||||
/**
|
||||
* 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 SettingsActivity extends AppCompatPreferenceActivity {
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (preference == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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(), ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setupActionBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the {@link android.app.ActionBar}, if the API is available.
|
||||
*/
|
||||
private void setupActionBar() {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
// Show the Up button in the action bar.
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean onIsMultiPane() {
|
||||
return isXLargeTablet(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public void onBuildHeaders(List<Header> target) {
|
||||
loadHeadersFromResource(R.xml.pref_headers, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method stops fragment injection in malicious applications.
|
||||
* Make sure to deny any unknown fragments here.
|
||||
*/
|
||||
protected boolean isValidFragment(String fragmentName) {
|
||||
return PreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| GeneralPreferenceFragment.class.getName().equals(fragmentName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
// 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("agc_host"));
|
||||
bindPreferenceSummaryToValue(findPreference("agc_port"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
startActivity(new Intent(getActivity(), SettingsActivity.class));
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
app/src/main/res/drawable/ic_info_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_info_black_24dp.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm1,15h-2v-6h2v6zm0,-8h-2V7h2v2z"/>
|
||||
</vector>
|
||||
@@ -1,4 +1,5 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
@@ -10,17 +11,17 @@
|
||||
layout="@layout/layout_indicator_lights"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|top" />
|
||||
android:layout_gravity="start|top"/>
|
||||
|
||||
<include
|
||||
layout="@layout/layout_7seg"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|top" />
|
||||
android:layout_gravity="end|top"/>
|
||||
|
||||
<include
|
||||
layout="@layout/layout_keyboard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|bottom" />
|
||||
android:layout_gravity="center_horizontal|bottom"/>
|
||||
</FrameLayout>
|
||||
12
app/src/main/res/menu/dsky_menu.xml
Normal file
12
app/src/main/res/menu/dsky_menu.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_connect"
|
||||
android:title="Connect"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:title="Settings"
|
||||
app:showAsAction="never"/>
|
||||
</menu>
|
||||
@@ -1,3 +1,10 @@
|
||||
<resources>
|
||||
<string name="app_name">androidDSKY</string>
|
||||
|
||||
<!-- Strings related to Settings -->
|
||||
<string name="title_activity_settings">Settings</string>
|
||||
<string name="pref_title_auto_connect">Auto-connect on startup</string>
|
||||
<string name="pref_description_auto_connect">Automatically connect to remote VirtualAGC when launching the app?</string>
|
||||
<string name="pref_title_agc_host">VirtualAGC host</string>
|
||||
<string name="pref_title_agc_port">VirtualAGC port</string>
|
||||
</resources>
|
||||
|
||||
24
app/src/main/res/xml/pref_general.xml
Normal file
24
app/src/main/res/xml/pref_general.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="auto_connect"
|
||||
android:summary="@string/pref_description_auto_connect"
|
||||
android:title="@string/pref_title_auto_connect"/>
|
||||
|
||||
<!-- NOTE: EditTextPreference accepts EditText attributes. -->
|
||||
<!-- NOTE: EditTextPreference's summary should be set to its value by the activity code. -->
|
||||
<EditTextPreference
|
||||
android:inputType="textUri"
|
||||
android:key="agc_host"
|
||||
android:maxLines="1"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="@string/pref_title_agc_host"/>
|
||||
<EditTextPreference
|
||||
android:defaultValue="19697"
|
||||
android:key="agc_port"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="@string/pref_title_agc_port"/>
|
||||
</PreferenceScreen>
|
||||
10
app/src/main/res/xml/pref_headers.xml
Normal file
10
app/src/main/res/xml/pref_headers.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- These settings headers are only used on tablets. -->
|
||||
|
||||
<header
|
||||
android:fragment="de.rumpold.androiddsky.ui.SettingsActivity$GeneralPreferenceFragment"
|
||||
android:icon="@drawable/ic_info_black_24dp"
|
||||
android:title="@string/pref_header_general"/>
|
||||
|
||||
</preference-headers>
|
||||
Reference in New Issue
Block a user