mirror of
https://gitlab.com/neothefox/LayTray
synced 2026-03-23 21:54:54 +03:00
Added settings
Added "about" page Now the Notification can be configured Now the user would be notified if the service is disabled
This commit is contained in:
parent
7a7ccd76d6
commit
3117a0dff5
@ -23,6 +23,7 @@ dependencies {
|
|||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'com.android.support:appcompat-v7:26.1.0'
|
implementation 'com.android.support:appcompat-v7:26.1.0'
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||||
|
implementation 'com.android.support:support-v4:26.1.0'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||||
|
|||||||
@ -10,25 +10,37 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
<activity android:name=".MainActivity">
|
<activity android:name=".MainActivity">
|
||||||
<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" />
|
|
||||||
</intent-filter>
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".IconService"
|
android:name=".IconService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:summary="A simple keyboard layout indicator for physical keyboards"
|
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
|
||||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
|
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.accessibilityservice.AccessibilityService"></action>
|
<action android:name="android.accessibilityservice.AccessibilityService" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".SettingsActivity"
|
||||||
|
android:label="@string/title_activity_settings"
|
||||||
|
android:parentActivityName=".MainActivity">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value="space.neothefox.laytray.MainActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".AboutActivity"
|
||||||
|
android:parentActivityName=".MainActivity">
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
13
app/src/main/java/space/neothefox/laytray/AboutActivity.java
Normal file
13
app/src/main/java/space/neothefox/laytray/AboutActivity.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package space.neothefox.laytray;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class AboutActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_about);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
package space.neothefox.laytray;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.accessibility.AccessibilityEvent;
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
|
|
||||||
@ -22,9 +23,10 @@ implements SharedPreferences.OnSharedPreferenceChangeListener{
|
|||||||
|
|
||||||
public String TAG = "layicon";
|
public String TAG = "layicon";
|
||||||
private final AccessibilityServiceInfo serviceInfo = new AccessibilityServiceInfo();
|
private final AccessibilityServiceInfo serviceInfo = new AccessibilityServiceInfo();
|
||||||
//Map<CharSequence, String> layoutText = new HashMap<>();
|
|
||||||
|
|
||||||
SharedPreferences layouts;
|
SharedPreferences layouts;
|
||||||
|
SharedPreferences options;
|
||||||
|
String lastToast;
|
||||||
|
|
||||||
NotificationManager iconManager;
|
NotificationManager iconManager;
|
||||||
|
|
||||||
@ -38,11 +40,11 @@ implements SharedPreferences.OnSharedPreferenceChangeListener{
|
|||||||
serviceInfo.notificationTimeout = 100;
|
serviceInfo.notificationTimeout = 100;
|
||||||
this.setServiceInfo(serviceInfo);
|
this.setServiceInfo(serviceInfo);
|
||||||
layouts = getSharedPreferences("layouts", 0);
|
layouts = getSharedPreferences("layouts", 0);
|
||||||
|
options = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||||
|
lastToast = "EMPT";
|
||||||
|
//options.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
iconManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
iconManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
//layoutText.put("Русский", "RU");
|
|
||||||
//layoutText.put("Буквы (АБВ)", "EN");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateNotification(String toast)
|
protected void updateNotification(String toast)
|
||||||
@ -56,22 +58,26 @@ implements SharedPreferences.OnSharedPreferenceChangeListener{
|
|||||||
layoutsEditor.commit();
|
layoutsEditor.commit();
|
||||||
textIcon = "??";
|
textIcon = "??";
|
||||||
}
|
}
|
||||||
Icon smallIcon = Icon.createWithBitmap(textAsBitmap(textIcon, 48, Color.WHITE));
|
Icon smallIcon = Icon.createWithBitmap(textAsBitmap(textIcon,
|
||||||
|
Integer.parseInt(options.getString("textSize", "48")),
|
||||||
|
options.getBoolean("textFakeBold", true),
|
||||||
|
Color.WHITE));
|
||||||
|
|
||||||
indicator = new Notification.Builder(this)
|
indicator = new Notification.Builder(this)
|
||||||
.setSmallIcon(smallIcon)
|
.setSmallIcon(smallIcon)
|
||||||
.setContentTitle(toast)
|
.setContentTitle(toast)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
|
.setPriority(Integer.parseInt(options.getString("notificationImportance", "0")))
|
||||||
.build();
|
.build();
|
||||||
iconManager.notify(0, indicator);
|
iconManager.notify(0, indicator);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Borrowed from Ted Hopp from StackOverflow
|
//Borrowed from Ted Hopp from StackOverflow
|
||||||
public Bitmap textAsBitmap(String text, float textSize, int textColor) {
|
public Bitmap textAsBitmap(String text, float textSize, boolean fakeBold, int textColor) {
|
||||||
Paint paint = new Paint(ANTI_ALIAS_FLAG);
|
Paint paint = new Paint(ANTI_ALIAS_FLAG);
|
||||||
paint.setTextSize(textSize);
|
paint.setTextSize(textSize);
|
||||||
paint.setFakeBoldText(true);
|
paint.setFakeBoldText(fakeBold);
|
||||||
paint.setColor(textColor);
|
paint.setColor(textColor);
|
||||||
paint.setTextAlign(Paint.Align.LEFT);
|
paint.setTextAlign(Paint.Align.LEFT);
|
||||||
float baseline = -paint.ascent(); // ascent() is negative
|
float baseline = -paint.ascent(); // ascent() is negative
|
||||||
@ -91,10 +97,10 @@ implements SharedPreferences.OnSharedPreferenceChangeListener{
|
|||||||
{
|
{
|
||||||
Log.d(TAG, "Caught a Toast: ");
|
Log.d(TAG, "Caught a Toast: ");
|
||||||
Log.d(TAG, (String)event.getPackageName());
|
Log.d(TAG, (String)event.getPackageName());
|
||||||
String toast = (String)event.getText().get(0);
|
lastToast = (String)event.getText().get(0);
|
||||||
Log.d(TAG, toast);
|
Log.d(TAG, lastToast);
|
||||||
|
|
||||||
updateNotification(toast);
|
updateNotification(lastToast);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -110,6 +116,6 @@ implements SharedPreferences.OnSharedPreferenceChangeListener{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
layouts = getSharedPreferences("layouts", 0);
|
updateNotification(lastToast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
package space.neothefox.laytray;
|
package space.neothefox.laytray;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.support.constraint.Guideline;
|
import android.provider.Settings;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Gravity;
|
import android.text.TextUtils;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@ -13,8 +18,8 @@ import android.widget.EditText;
|
|||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Space;
|
import android.widget.Space;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity
|
public class MainActivity extends AppCompatActivity
|
||||||
@ -38,6 +43,12 @@ implements View.OnClickListener, SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
saveButton.setOnClickListener(this);
|
saveButton.setOnClickListener(this);
|
||||||
layouts.registerOnSharedPreferenceChangeListener(this);
|
layouts.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
if (!isAccessibilitySettingsOn(getApplicationContext())) {
|
||||||
|
Toast.makeText(this, "You have to enable the service!",
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateLayouts()
|
protected void updateLayouts()
|
||||||
@ -55,7 +66,8 @@ implements View.OnClickListener, SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
entry.getValue().toString());
|
entry.getValue().toString());
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
addLine(layoutLister, entry.getKey(), entry.getValue().toString());
|
if(entry.getKey() != "EMPT")
|
||||||
|
addLine(layoutLister, entry.getKey(), entry.getValue().toString());
|
||||||
}
|
}
|
||||||
if(i == 0)
|
if(i == 0)
|
||||||
{
|
{
|
||||||
@ -76,6 +88,7 @@ implements View.OnClickListener, SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
layoutsEditor.clear();
|
layoutsEditor.clear();
|
||||||
layoutsEditor.putString("Русский", "RU");
|
layoutsEditor.putString("Русский", "RU");
|
||||||
layoutsEditor.putString("Буквы (АБВ)", "EN");
|
layoutsEditor.putString("Буквы (АБВ)", "EN");
|
||||||
|
layoutsEditor.putString("EMPT", "??");
|
||||||
layoutsEditor.commit();
|
layoutsEditor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +166,46 @@ implements View.OnClickListener, SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Accessibility check by Antoine Bolvy
|
||||||
|
private boolean isAccessibilitySettingsOn(Context mContext) {
|
||||||
|
int accessibilityEnabled = 0;
|
||||||
|
final String service = getPackageName() + "/" + IconService.class.getCanonicalName();
|
||||||
|
try {
|
||||||
|
accessibilityEnabled = Settings.Secure.getInt(
|
||||||
|
mContext.getApplicationContext().getContentResolver(),
|
||||||
|
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
|
||||||
|
Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
|
||||||
|
} catch (Settings.SettingNotFoundException e) {
|
||||||
|
Log.e(TAG, "Error finding setting, default accessibility to not found: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
|
||||||
|
|
||||||
|
if (accessibilityEnabled == 1) {
|
||||||
|
Log.v(TAG, "Accessibility service enabled");
|
||||||
|
String settingValue = Settings.Secure.getString(
|
||||||
|
mContext.getApplicationContext().getContentResolver(),
|
||||||
|
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
|
||||||
|
if (settingValue != null) {
|
||||||
|
mStringColonSplitter.setString(settingValue);
|
||||||
|
while (mStringColonSplitter.hasNext()) {
|
||||||
|
String accessibilityService = mStringColonSplitter.next();
|
||||||
|
|
||||||
|
Log.v(TAG, "-------------- > accessibilityService :: " + accessibilityService + " " + service);
|
||||||
|
if (accessibilityService.equalsIgnoreCase(service)) {
|
||||||
|
Log.v(TAG, "We've found the correct setting - accessibility is switched on!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.v(TAG, "Accessibility is disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
switch(v.getId())
|
switch(v.getId())
|
||||||
@ -166,6 +219,28 @@ implements View.OnClickListener, SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.menu, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch(item.getItemId())
|
||||||
|
{
|
||||||
|
case R.id.settings:
|
||||||
|
startActivity(new Intent(this, SettingsActivity.class));
|
||||||
|
return true;
|
||||||
|
case R.id.about:
|
||||||
|
startActivity(new Intent(this, AboutActivity.class));
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
layouts = getSharedPreferences("layouts", 0);
|
layouts = getSharedPreferences("layouts", 0);
|
||||||
|
|||||||
214
app/src/main/java/space/neothefox/laytray/SettingsActivity.java
Normal file
214
app/src/main/java/space/neothefox/laytray/SettingsActivity.java
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
package space.neothefox.laytray;
|
||||||
|
|
||||||
|
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.support.v7.app.ActionBar;
|
||||||
|
import android.preference.PreferenceFragment;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.preference.RingtonePreference;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.support.v4.app.NavUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
// 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) {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||||
|
int id = item.getItemId();
|
||||||
|
if (id == android.R.id.home) {
|
||||||
|
if (!super.onMenuItemSelected(featureId, item)) {
|
||||||
|
NavUtils.navigateUpFromSameTask(this);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onMenuItemSelected(featureId, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@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)
|
||||||
|
|| NotificationPreferenceFragment.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("default_app_name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
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("notificationImportance"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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>
|
||||||
@ -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="M11.5,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zm6.5,-6v-5.5c0,-3.07 -2.13,-5.64 -5,-6.32V3.5c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,2.67 10,3.5v0.68c-2.87,0.68 -5,3.25 -5,6.32V16l-2,2v1h17v-1l-2,-2z" />
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/ic_sync_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_sync_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 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01,-.25 1.97,-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0,-4.42,-3.58,-8,-8,-8zm0 14c-3.31 0,-6,-2.69,-6,-6 0,-1.01.25,-1.97.7,-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4,-4,-4,-4v3z" />
|
||||||
|
</vector>
|
||||||
47
app/src/main/res/layout/activity_about.xml
Normal file
47
app/src/main/res/layout/activity_about.xml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.constraint.ConstraintLayout 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"
|
||||||
|
tools:context=".AboutActivity">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="138dp"
|
||||||
|
android:layout_marginStart="138dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:src="@mipmap/ic_launcher_foreground"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="163dp"
|
||||||
|
android:layout_marginStart="163dp"
|
||||||
|
android:layout_marginTop="68dp"
|
||||||
|
android:text="@string/about_text"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/imageView" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView4"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="168dp"
|
||||||
|
android:layout_marginStart="168dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Large"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/imageView" />
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
@ -53,9 +53,10 @@
|
|||||||
android:layout_width="81dp"
|
android:layout_width="81dp"
|
||||||
android:layout_height="41dp"
|
android:layout_height="41dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
android:text="Save"
|
android:text="Save"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
tools:layout_editor_absoluteY="16dp" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView2"
|
android:id="@+id/textView2"
|
||||||
@ -66,4 +67,5 @@
|
|||||||
android:text="by NeoTheFox"
|
android:text="by NeoTheFox"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
@ -3,4 +3,38 @@
|
|||||||
<string name="service_description">A simple layout icon</string>
|
<string name="service_description">A simple layout icon</string>
|
||||||
<string name="accessibility_summary">LayTray needs to be enabled as an accessibility app, because the only way to get layout info on Android is by monitoring the Toast notification. Right now it monitors Blackberry Keyboard exclusively.</string>
|
<string name="accessibility_summary">LayTray needs to be enabled as an accessibility app, because the only way to get layout info on Android is by monitoring the Toast notification. Right now it monitors Blackberry Keyboard exclusively.</string>
|
||||||
<string name="activity_info">Associate layout name with layout icon</string>
|
<string name="activity_info">Associate layout name with layout icon</string>
|
||||||
|
<string name="title_activity_settings">Settings</string>
|
||||||
|
|
||||||
|
<!-- Strings related to Settings -->
|
||||||
|
|
||||||
|
<!-- Example General settings -->
|
||||||
|
<string name="pref_header_general">General</string>
|
||||||
|
|
||||||
|
<string name="pref_title_default_app_name">App to monitor</string>
|
||||||
|
<string name="pref_default_app_name">com.blackberry.keyboard</string>
|
||||||
|
|
||||||
|
<string name="pref_title_notification_importance">Notification importance</string>
|
||||||
|
<string-array name="pref_notification_importance_list_titles">
|
||||||
|
<item>Default</item>
|
||||||
|
<item>High</item>
|
||||||
|
<item>Low</item>
|
||||||
|
<item>Min</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="pref_notification_importance_list_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>-1</item>
|
||||||
|
<item>-2</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Example settings for Notifications -->
|
||||||
|
<string name="pref_header_notifications">Notifications</string>
|
||||||
|
|
||||||
|
<string name="pref_title_text_fake_bold">Bold</string>
|
||||||
|
<string name="pref_title_text_size">Text size</string>
|
||||||
|
|
||||||
|
<string name="about_text">A layout icon by NeoTheFox \n
|
||||||
|
Distributed on the terms of GNU GPLv3 licence</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
10
app/src/main/res/xml/pref_general.xml
Normal file
10
app/src/main/res/xml/pref_general.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="@string/pref_default_app_name"
|
||||||
|
android:key="default_app_name"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:title="@string/pref_title_default_app_name" />
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
15
app/src/main/res/xml/pref_headers.xml
Normal file
15
app/src/main/res/xml/pref_headers.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<!-- These settings headers are only used on tablets. -->
|
||||||
|
|
||||||
|
<header
|
||||||
|
android:fragment="space.neothefox.laytray.SettingsActivity$GeneralPreferenceFragment"
|
||||||
|
android:icon="@drawable/ic_info_black_24dp"
|
||||||
|
android:title="@string/pref_header_general" />
|
||||||
|
|
||||||
|
<header
|
||||||
|
android:fragment="space.neothefox.laytray.SettingsActivity$NotificationPreferenceFragment"
|
||||||
|
android:icon="@drawable/ic_notifications_black_24dp"
|
||||||
|
android:title="@string/pref_header_notifications" />
|
||||||
|
|
||||||
|
</preference-headers>
|
||||||
27
app/src/main/res/xml/pref_notification.xml
Normal file
27
app/src/main/res/xml/pref_notification.xml
Normal file
@ -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. -->
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:entries="@array/pref_notification_importance_list_titles"
|
||||||
|
android:entryValues="@array/pref_notification_importance_list_values"
|
||||||
|
android:key="notificationImportance"
|
||||||
|
android:negativeButtonText="@null"
|
||||||
|
android:positiveButtonText="@null"
|
||||||
|
android:title="@string/pref_title_notification_importance" />
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="textFakeBold"
|
||||||
|
android:title="@string/pref_title_text_fake_bold" />
|
||||||
|
|
||||||
|
<!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="48"
|
||||||
|
android:key="textSize"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="number"
|
||||||
|
android:title="@string/pref_title_text_size" />
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
Loading…
x
Reference in New Issue
Block a user