UI: SettingsActivity

This commit is contained in:
zt515
2017-06-12 18:46:38 +08:00
parent 9b29779be6
commit 0e6207b5f3
15 changed files with 286 additions and 156 deletions

View File

@ -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" />

View File

@ -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();
}
}

View 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
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -0,0 +1,10 @@
package io.neoterm.view.tab
import de.mrapp.android.tabswitcher.Tab
/**
* @author kiva
*/
interface CloseTabProvider {
fun closeTab(tab: Tab)
}

View File

@ -47,7 +47,3 @@ class TermTab(title: CharSequence) : Tab(title) {
closeTabProvider?.closeTab(this)
}
}
interface CloseTabProvider {
fun closeTab(tab: Tab)
}

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
</PreferenceScreen>

View File

@ -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>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
</PreferenceScreen>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
</PreferenceScreen>