UI: SettingsActivity
This commit is contained in:
@ -27,6 +27,18 @@
|
||||
android:name=".ui.settings.SettingActivity"
|
||||
android:theme="@style/Theme.AppCompat" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.settings.GeneralSettingsActivity"
|
||||
android:theme="@style/Theme.AppCompat" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.settings.UISettingsActivity"
|
||||
android:theme="@style/Theme.AppCompat" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.settings.PackageSettingsActivity"
|
||||
android:theme="@style/Theme.AppCompat" />
|
||||
|
||||
<service
|
||||
android:name=".services.NeoTermService"
|
||||
android:enabled="true" />
|
||||
|
@ -1,137 +0,0 @@
|
||||
package io.neoterm.services;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.WakefulBroadcastReceiver;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.neoterm.ui.NeoTermActivity;
|
||||
import io.neoterm.R;
|
||||
import io.neoterm.backend.EmulatorDebug;
|
||||
import io.neoterm.backend.TerminalSession;
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
|
||||
public class NeoTermService extends Service {
|
||||
public class NeoTermBinder extends Binder {
|
||||
public NeoTermService service = NeoTermService.this;
|
||||
}
|
||||
|
||||
public static final String ACTION_SERVICE_STOP = "neoterm.action.service.stop";
|
||||
|
||||
private static final int NOTIFICATION_ID = 52019;
|
||||
|
||||
private final NeoTermBinder neoTermBinder = new NeoTermBinder();
|
||||
private final List<TerminalSession> mTerminalSessions = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
startForeground(NOTIFICATION_ID, createNotification());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return neoTermBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
String action = intent.getAction();
|
||||
if (ACTION_SERVICE_STOP.equals(action)) {
|
||||
for (int i = 0; i < mTerminalSessions.size(); i++)
|
||||
mTerminalSessions.get(i).finishIfRunning();
|
||||
stopSelf();
|
||||
} else if (action != null) {
|
||||
Log.e(EmulatorDebug.LOG_TAG, "Unknown NeoTermService action: '" + action + "'");
|
||||
}
|
||||
|
||||
if ((flags & START_FLAG_REDELIVERY) == 0) {
|
||||
// Service is started by WBR, not restarted by system, so release the WakeLock from WBR.
|
||||
WakefulBroadcastReceiver.completeWakefulIntent(intent);
|
||||
}
|
||||
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stopForeground(true);
|
||||
|
||||
for (int i = 0; i < mTerminalSessions.size(); i++)
|
||||
mTerminalSessions.get(i).finishIfRunning();
|
||||
mTerminalSessions.clear();
|
||||
}
|
||||
|
||||
public List<TerminalSession> getSessions() {
|
||||
return mTerminalSessions;
|
||||
}
|
||||
|
||||
public TerminalSession createTermSession(String executablePath, String[] arguments, String cwd, String[] env, TerminalSession.SessionChangedCallback sessionCallback) {
|
||||
if (cwd == null) cwd = getFilesDir().getAbsolutePath();
|
||||
|
||||
boolean isLoginShell = false;
|
||||
|
||||
if (executablePath == null) {
|
||||
// Fall back to system shell as last resort:
|
||||
executablePath = "/system/bin/sh";
|
||||
isLoginShell = true;
|
||||
}
|
||||
|
||||
if (arguments == null) {
|
||||
arguments = new String[]{executablePath};
|
||||
}
|
||||
|
||||
int lastSlashIndex = executablePath.lastIndexOf('/');
|
||||
String processName = (isLoginShell ? "-" : "") +
|
||||
(lastSlashIndex == -1 ? executablePath : executablePath.substring(lastSlashIndex + 1));
|
||||
|
||||
TerminalSession session = new TerminalSession(executablePath, cwd, arguments, env, sessionCallback);
|
||||
mTerminalSessions.add(session);
|
||||
updateNotification();
|
||||
return session;
|
||||
}
|
||||
|
||||
public int removeTermSession(TerminalSession sessionToRemove) {
|
||||
int indexOfRemoved = mTerminalSessions.indexOf(sessionToRemove);
|
||||
mTerminalSessions.remove(indexOfRemoved);
|
||||
updateNotification();
|
||||
return indexOfRemoved;
|
||||
}
|
||||
|
||||
private void updateNotification() {
|
||||
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, createNotification());
|
||||
}
|
||||
|
||||
private Notification createNotification() {
|
||||
Intent notifyIntent = new Intent(this, NeoTermActivity.class);
|
||||
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0);
|
||||
|
||||
int sessionCount = mTerminalSessions.size();
|
||||
String contentText = sessionCount + " session" + (sessionCount == 1 ? "" : "s");
|
||||
|
||||
Notification.Builder builder = new Notification.Builder(this);
|
||||
builder.setContentTitle(getText(R.string.app_name));
|
||||
builder.setContentText(contentText);
|
||||
builder.setSmallIcon(R.drawable.ic_terminal_running);
|
||||
builder.setContentIntent(pendingIntent);
|
||||
builder.setOngoing(true);
|
||||
builder.setShowWhen(false);
|
||||
builder.setColor(0xFF000000);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
134
app/src/main/java/io/neoterm/services/NeoTermService.kt
Normal file
134
app/src/main/java/io/neoterm/services/NeoTermService.kt
Normal file
@ -0,0 +1,134 @@
|
||||
package io.neoterm.services
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.support.v4.content.WakefulBroadcastReceiver
|
||||
import android.util.Log
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import io.neoterm.ui.NeoTermActivity
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.EmulatorDebug
|
||||
import io.neoterm.backend.TerminalSession
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
|
||||
class NeoTermService : Service() {
|
||||
inner class NeoTermBinder : Binder() {
|
||||
var service = this@NeoTermService
|
||||
}
|
||||
|
||||
private val neoTermBinder = NeoTermBinder()
|
||||
private val mTerminalSessions = ArrayList<TerminalSession>()
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
startForeground(NOTIFICATION_ID, createNotification())
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return neoTermBinder
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
val action = intent.action
|
||||
if (ACTION_SERVICE_STOP == action) {
|
||||
for (i in mTerminalSessions.indices)
|
||||
mTerminalSessions[i].finishIfRunning()
|
||||
stopSelf()
|
||||
} else if (action != null) {
|
||||
Log.e(EmulatorDebug.LOG_TAG, "Unknown NeoTermService action: '$action'")
|
||||
}
|
||||
|
||||
if (flags and Service.START_FLAG_REDELIVERY == 0) {
|
||||
// Service is started by WBR, not restarted by system, so release the WakeLock from WBR.
|
||||
WakefulBroadcastReceiver.completeWakefulIntent(intent)
|
||||
}
|
||||
|
||||
return Service.START_NOT_STICKY
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
stopForeground(true)
|
||||
|
||||
for (i in mTerminalSessions.indices)
|
||||
mTerminalSessions[i].finishIfRunning()
|
||||
mTerminalSessions.clear()
|
||||
}
|
||||
|
||||
val sessions: List<TerminalSession>
|
||||
get() = mTerminalSessions
|
||||
|
||||
fun createTermSession(executablePath: String?, arguments: Array<String>?, cwd: String?, env: Array<String>?, sessionCallback: TerminalSession.SessionChangedCallback?): TerminalSession {
|
||||
var executablePath = executablePath
|
||||
var arguments = arguments
|
||||
var cwd = cwd
|
||||
if (cwd == null) cwd = filesDir.absolutePath
|
||||
|
||||
var isLoginShell = false
|
||||
|
||||
if (executablePath == null) {
|
||||
// Fall back to system shell as last resort:
|
||||
executablePath = "/system/bin/sh"
|
||||
isLoginShell = true
|
||||
}
|
||||
|
||||
if (arguments == null) {
|
||||
arguments = arrayOf<String>(executablePath)
|
||||
}
|
||||
|
||||
val lastSlashIndex = executablePath.lastIndexOf('/')
|
||||
val processName = (if (isLoginShell) "-" else "") + if (lastSlashIndex == -1) executablePath else executablePath.substring(lastSlashIndex + 1)
|
||||
|
||||
val session = TerminalSession(executablePath, cwd, arguments, env, sessionCallback)
|
||||
mTerminalSessions.add(session)
|
||||
updateNotification()
|
||||
return session
|
||||
}
|
||||
|
||||
fun removeTermSession(sessionToRemove: TerminalSession): Int {
|
||||
val indexOfRemoved = mTerminalSessions.indexOf(sessionToRemove)
|
||||
mTerminalSessions.removeAt(indexOfRemoved)
|
||||
updateNotification()
|
||||
return indexOfRemoved
|
||||
}
|
||||
|
||||
private fun updateNotification() {
|
||||
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).notify(NOTIFICATION_ID, createNotification())
|
||||
}
|
||||
|
||||
private fun createNotification(): Notification {
|
||||
val notifyIntent = Intent(this, NeoTermActivity::class.java)
|
||||
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
val pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0)
|
||||
|
||||
val sessionCount = mTerminalSessions.size
|
||||
val contentText = sessionCount.toString() + " session" + if (sessionCount == 1) "" else "s"
|
||||
|
||||
val builder = Notification.Builder(this)
|
||||
builder.setContentTitle(getText(R.string.app_name))
|
||||
builder.setContentText(contentText)
|
||||
builder.setSmallIcon(R.drawable.ic_terminal_running)
|
||||
builder.setContentIntent(pendingIntent)
|
||||
builder.setOngoing(true)
|
||||
builder.setShowWhen(false)
|
||||
builder.setColor(0xFF000000.toInt())
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val ACTION_SERVICE_STOP = "neoterm.action.service.stop"
|
||||
|
||||
private val NOTIFICATION_ID = 52019
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package io.neoterm.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatPreferenceActivity
|
||||
import android.view.MenuItem
|
||||
import io.neoterm.R
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class GeneralSettingsActivity : AppCompatPreferenceActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar.title = getString(R.string.general_settings)
|
||||
supportActionBar.setDisplayHomeAsUpEnabled(true)
|
||||
addPreferencesFromResource(R.xml.setting_general)
|
||||
}
|
||||
|
||||
override fun onBuildHeaders(target: MutableList<Header>?) {
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||
when (item?.itemId) {
|
||||
android.R.id.home ->
|
||||
finish()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package io.neoterm.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatPreferenceActivity
|
||||
import android.view.MenuItem
|
||||
import io.neoterm.R
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class PackageSettingsActivity : AppCompatPreferenceActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar.title = getString(R.string.package_settings)
|
||||
supportActionBar.setDisplayHomeAsUpEnabled(true)
|
||||
addPreferencesFromResource(R.xml.settings_package)
|
||||
}
|
||||
|
||||
override fun onBuildHeaders(target: MutableList<Header>?) {
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||
when (item?.itemId) {
|
||||
android.R.id.home ->
|
||||
finish()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ class SettingActivity : AppCompatPreferenceActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar.title = getString(R.string.menu_settings)
|
||||
supportActionBar.title = getString(R.string.settings)
|
||||
supportActionBar.setDisplayHomeAsUpEnabled(true)
|
||||
addPreferencesFromResource(R.xml.settings_main)
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package io.neoterm.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatPreferenceActivity
|
||||
import android.view.MenuItem
|
||||
import io.neoterm.R
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class UISettingsActivity : AppCompatPreferenceActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar.title = getString(R.string.ui_settings)
|
||||
supportActionBar.setDisplayHomeAsUpEnabled(true)
|
||||
addPreferencesFromResource(R.xml.settings_ui)
|
||||
}
|
||||
|
||||
override fun onBuildHeaders(target: MutableList<Header>?) {
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||
when (item?.itemId) {
|
||||
android.R.id.home ->
|
||||
finish()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
10
app/src/main/java/io/neoterm/view/tab/CloseTabProvider.kt
Normal file
10
app/src/main/java/io/neoterm/view/tab/CloseTabProvider.kt
Normal file
@ -0,0 +1,10 @@
|
||||
package io.neoterm.view.tab
|
||||
|
||||
import de.mrapp.android.tabswitcher.Tab
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
interface CloseTabProvider {
|
||||
fun closeTab(tab: Tab)
|
||||
}
|
@ -47,7 +47,3 @@ class TermTab(title: CharSequence) : Tab(title) {
|
||||
closeTabProvider?.closeTab(this)
|
||||
}
|
||||
}
|
||||
|
||||
interface CloseTabProvider {
|
||||
fun closeTab(tab: Tab)
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ License.
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_item_settings"
|
||||
android:title="@string/menu_settings"
|
||||
android:title="@string/settings"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
</menu>
|
@ -5,6 +5,11 @@
|
||||
<string name="text_selection_more">More</string>
|
||||
|
||||
<string name="toggle_tab_switcher_menu_item">Toggle switcher</string>
|
||||
<string name="menu_settings">Settings</string>
|
||||
<string name="new_session">New session</string>
|
||||
|
||||
<string name="about">About</string>
|
||||
<string name="settings">Settings</string>
|
||||
<string name="general_settings">General Settings</string>
|
||||
<string name="ui_settings">UI Settings</string>
|
||||
<string name="package_settings">Package Settings</string>
|
||||
</resources>
|
||||
|
4
app/src/main/res/xml/setting_general.xml
Normal file
4
app/src/main/res/xml/setting_general.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</PreferenceScreen>
|
@ -1,20 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<Preference
|
||||
android:summary="设置通用的选项"
|
||||
android:title="通用设置" />
|
||||
<Preference android:title="@string/general_settings">
|
||||
<intent
|
||||
android:targetClass="io.neoterm.ui.settings.GeneralSettingsActivity"
|
||||
android:targetPackage="io.neoterm" />
|
||||
</Preference>
|
||||
|
||||
<Preference
|
||||
android:summary="设置界面有关的选项"
|
||||
android:title="界面选项" />
|
||||
<Preference android:title="@string/ui_settings" >
|
||||
<intent
|
||||
android:targetClass="io.neoterm.ui.settings.UISettingsActivity"
|
||||
android:targetPackage="io.neoterm" />
|
||||
</Preference>
|
||||
|
||||
<Preference
|
||||
android:title="软件包选项"
|
||||
android:summary="设置软件包有关的选项" />
|
||||
|
||||
<Preference
|
||||
android:title="关于"/>
|
||||
<Preference android:title="@string/package_settings" >
|
||||
<intent
|
||||
android:targetClass="io.neoterm.ui.settings.PackageSettingsActivity"
|
||||
android:targetPackage="io.neoterm" />
|
||||
</Preference>
|
||||
|
||||
<Preference android:title="@string/about" >
|
||||
<intent
|
||||
android:targetClass="io.neoterm.ui.AboutActivity"
|
||||
android:targetPackage="io.neoterm" />
|
||||
</Preference>
|
||||
|
||||
</PreferenceScreen>
|
4
app/src/main/res/xml/settings_package.xml
Normal file
4
app/src/main/res/xml/settings_package.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</PreferenceScreen>
|
4
app/src/main/res/xml/settings_ui.xml
Normal file
4
app/src/main/res/xml/settings_ui.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</PreferenceScreen>
|
Reference in New Issue
Block a user