kopia lustrzana https://github.com/ge0rg/aprsdroid
messaging activity and listadapter stubs
rodzic
bb12fefc4d
commit
a8dd25f3bb
|
@ -33,6 +33,9 @@
|
|||
<activity android:name=".StationActivity" android:label="@string/app_sta"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
/>
|
||||
<activity android:name=".MessageActivity" android:label="@string/app_sta"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
/>
|
||||
<activity android:name=".PrefsAct" android:label="@string/app_prefs" />
|
||||
<activity android:name=".BackendPrefs" android:label="@string/app_prefs" />
|
||||
<activity android:name=".MapAct" android:label="@string/app_map"
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
android:id="@+id/message_act"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
>
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:id="@+id/buttonlayout"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
>
|
||||
<EditText android:id="@+id/msginput"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:layout_weight="1"
|
||||
android:inputType="textShortMessage"
|
||||
/>
|
||||
<Button android:id="@+id/msgsend"
|
||||
android:layout_width="60sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@android:string/ok"
|
||||
android:enabled="false"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/details" android:title="@string/app_sta" />
|
||||
<item android:id="@+id/message" android:title="Message" />
|
||||
<item android:id="@+id/mapbutton" android:title="@string/sta_map" />
|
||||
<item android:id="@+id/aprsfibutton" android:title="@string/sta_aprsfi" />
|
||||
<item android:id="@+id/qrzcombutton" android:title="@string/sta_qrzcom" />
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
package org.aprsdroid.app
|
||||
|
||||
import _root_.android.app.ListActivity
|
||||
import _root_.android.content._
|
||||
import _root_.android.database.Cursor
|
||||
import _root_.android.net.Uri
|
||||
import _root_.android.os.{Bundle, Handler}
|
||||
import _root_.android.text.{Editable, TextWatcher}
|
||||
import _root_.android.util.Log
|
||||
import _root_.android.view.{Menu, MenuItem, View, Window}
|
||||
import _root_.android.view.View.OnClickListener
|
||||
import _root_.android.widget.{Button, EditText, ListView}
|
||||
|
||||
class MessageActivity extends LoadingListActivity
|
||||
with OnClickListener with TextWatcher {
|
||||
val TAG = "APRSdroid.Message"
|
||||
lazy val targetcall = getIntent().getStringExtra("call")
|
||||
|
||||
lazy val storage = StorageDatabase.open(this)
|
||||
|
||||
lazy val mycall = prefs.getCallSsid()
|
||||
lazy val pla = new MessageListAdapter(this, prefs, mycall, targetcall)
|
||||
lazy val locReceiver = new LocationReceiver2[Cursor](load_cursor, replace_cursor, cancel_cursor)
|
||||
|
||||
lazy val msginput = findView[EditText](R.id.msginput)
|
||||
lazy val msgsend = findView[Button](R.id.msgsend)
|
||||
|
||||
override def onCreate(savedInstanceState: Bundle) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.message_act)
|
||||
|
||||
getListView().setOnCreateContextMenuListener(this);
|
||||
|
||||
onStartLoading()
|
||||
setListAdapter(pla)
|
||||
registerReceiver(locReceiver, new IntentFilter(AprsService.UPDATE))
|
||||
locReceiver.startTask(null)
|
||||
|
||||
msginput.addTextChangedListener(this)
|
||||
msgsend.setOnClickListener(this)
|
||||
|
||||
setTitle(getString(R.string.app_sta) + ": " + targetcall)
|
||||
}
|
||||
|
||||
override def onDestroy() {
|
||||
super.onDestroy()
|
||||
pla.onDestroy()
|
||||
unregisterReceiver(locReceiver)
|
||||
}
|
||||
|
||||
override def onCreateOptionsMenu(menu : Menu) : Boolean = {
|
||||
getMenuInflater().inflate(R.menu.options, menu);
|
||||
true
|
||||
}
|
||||
|
||||
override def onListItemClick(l : ListView, v : View, position : Int, id : Long) {
|
||||
//super.onListItemClick(l, v, position, id)
|
||||
val c = getListView().getItemAtPosition(position).asInstanceOf[Cursor]
|
||||
val call = c.getString(StorageDatabase.Position.COLUMN_CALL)
|
||||
Log.d("MessageActivity", "onListItemClick: %s".format(call))
|
||||
|
||||
if (targetcall == call) {
|
||||
// click on own callssid
|
||||
trackOnMap(call)
|
||||
} else {
|
||||
openDetails(call)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
// TextWatcher for msginput
|
||||
override def afterTextChanged(s : Editable) {
|
||||
msgsend.setEnabled(msginput.getText().length() > 0)
|
||||
}
|
||||
override def beforeTextChanged(s : CharSequence, start : Int, before : Int, count : Int) {
|
||||
}
|
||||
override def onTextChanged(s : CharSequence, start : Int, before : Int, count : Int) {
|
||||
}
|
||||
|
||||
def sendMessage() {
|
||||
val msg = msginput.getText().toString()
|
||||
if (msg.length() == 0)
|
||||
return
|
||||
Log.d("MessageActivity", "sending " + msg)
|
||||
msginput.setText(null)
|
||||
}
|
||||
|
||||
// button actions
|
||||
override def onClick(view : View) {
|
||||
Log.d(TAG, "onClick: " + view.getId)
|
||||
view.getId match {
|
||||
case R.id.msgsend =>
|
||||
sendMessage()
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
def load_cursor(i : Intent) = {
|
||||
val c = storage.getStaPosts(targetcall, "100")
|
||||
c.getCount()
|
||||
c
|
||||
}
|
||||
def replace_cursor(c : Cursor) {
|
||||
// do not call onStopLoading, PositionListAdapter takes much longer
|
||||
//onStopLoading()
|
||||
}
|
||||
def cancel_cursor(c : Cursor) {
|
||||
c.close()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package org.aprsdroid.app
|
||||
|
||||
import _root_.android.app.Activity
|
||||
import _root_.android.content._
|
||||
import _root_.android.database.Cursor
|
||||
import _root_.android.os.{AsyncTask, Bundle, Handler}
|
||||
import _root_.android.text.format.DateUtils
|
||||
import _root_.android.util.Log
|
||||
import _root_.android.view.View
|
||||
import _root_.android.widget.{SimpleCursorAdapter, TextView}
|
||||
|
||||
object MessageListAdapter {
|
||||
import StorageDatabase.Position._
|
||||
val LIST_FROM = Array(CALL, COMMENT, QRG)
|
||||
val LIST_TO = Array(R.id.station_call, R.id.listmessage, R.id.station_qrg)
|
||||
|
||||
val SINGLE = 0
|
||||
val NEIGHBORS = 1
|
||||
val SSIDS = 2
|
||||
}
|
||||
|
||||
class MessageListAdapter(context : Context, prefs : PrefsWrapper,
|
||||
mycall : String, targetcall : String)
|
||||
extends SimpleCursorAdapter(context, R.layout.stationview, null, MessageListAdapter.LIST_FROM, MessageListAdapter.LIST_TO) {
|
||||
|
||||
var my_lat = 0
|
||||
var my_lon = 0
|
||||
var reload_pending = 0
|
||||
lazy val storage = StorageDatabase.open(context)
|
||||
|
||||
reload()
|
||||
|
||||
lazy val locReceiver = new LocationReceiver2(load_cursor,
|
||||
replace_cursor, cancel_cursor)
|
||||
|
||||
context.registerReceiver(locReceiver, new IntentFilter(AprsService.UPDATE))
|
||||
|
||||
def getAgeColor(ts : Long) : Int = {
|
||||
val DARK = Array(0xff, 0x60, 0x60, 0x40)
|
||||
val BRIGHT = Array(0xff, 0xff, 0xff, 0xc0)
|
||||
val MAX = 30*60*1000
|
||||
val delta = (System.currentTimeMillis - ts).toInt
|
||||
val factor = if (delta < MAX) delta else MAX
|
||||
val mix = DARK zip BRIGHT map (t => { t._2 - (t._2 - t._1)*factor/MAX } )
|
||||
mix.reduceLeft(_*256 + _)
|
||||
}
|
||||
|
||||
// return compass bearing for a given value
|
||||
private val LETTERS = Array("N", "NE", "E", "SE", "S", "SW", "W", "NW")
|
||||
def getBearing(b : Double) = LETTERS(((b.toInt + 22 + 720) % 360) / 45)
|
||||
|
||||
override def bindView(view : View, context : Context, cursor : Cursor) {
|
||||
import StorageDatabase.Position._
|
||||
|
||||
// TODO: multidimensional mapping
|
||||
val distage = view.findViewById(R.id.station_distage).asInstanceOf[TextView]
|
||||
val call = cursor.getString(COLUMN_CALL)
|
||||
val ts = cursor.getLong(COLUMN_TS)
|
||||
val age = DateUtils.getRelativeTimeSpanString(context, ts)
|
||||
val lat = cursor.getInt(COLUMN_LAT)
|
||||
val lon = cursor.getInt(COLUMN_LON)
|
||||
val dist = Array[Float](0, 0)
|
||||
|
||||
if (call == mycall) {
|
||||
view.setBackgroundColor(0x4020ff20)
|
||||
} else if (call == targetcall) {
|
||||
view.setBackgroundColor(0x402020ff)
|
||||
} else
|
||||
view.setBackgroundColor(0)
|
||||
distage.setTextColor(getAgeColor(ts))
|
||||
view.findViewById(R.id.station_call).asInstanceOf[TextView].setTextColor(getAgeColor(ts))
|
||||
view.findViewById(R.id.station_qrg).asInstanceOf[TextView].setTextColor(getAgeColor(ts))
|
||||
val MCD = 1000000.
|
||||
android.location.Location.distanceBetween(my_lat/MCD, my_lon/MCD,
|
||||
lat/MCD, lon/MCD, dist)
|
||||
distage.setText("%1.1f km %s\n%s".format(dist(0)/1000., getBearing(dist(1)), age))
|
||||
super.bindView(view, context, cursor)
|
||||
}
|
||||
|
||||
def load_cursor(i : Intent) = {
|
||||
import MessageListAdapter._
|
||||
Benchmark("get my position") {
|
||||
val cursor = storage.getStaPosition(mycall)
|
||||
if (cursor.getCount() > 0) {
|
||||
cursor.moveToFirst()
|
||||
my_lat = cursor.getInt(StorageDatabase.Position.COLUMN_LAT)
|
||||
my_lon = cursor.getInt(StorageDatabase.Position.COLUMN_LON)
|
||||
}
|
||||
cursor.close()
|
||||
}
|
||||
val c = storage.getAllSsids(targetcall)
|
||||
Benchmark("getCount") { c.getCount() }
|
||||
c
|
||||
}
|
||||
|
||||
def replace_cursor(c : Cursor) {
|
||||
changeCursor(c)
|
||||
context.asInstanceOf[LoadingIndicator].onStopLoading()
|
||||
}
|
||||
def cancel_cursor(c : Cursor) {
|
||||
c.close()
|
||||
}
|
||||
|
||||
def reload() {
|
||||
locReceiver.startTask(null)
|
||||
}
|
||||
|
||||
def onDestroy() {
|
||||
context.unregisterReceiver(locReceiver)
|
||||
changeCursor(null)
|
||||
}
|
||||
}
|
|
@ -88,9 +88,19 @@ object StorageDatabase {
|
|||
val TABLE = "message"
|
||||
val _ID = "_id"
|
||||
val TS = "ts"
|
||||
val NEXTTS = "nextts"
|
||||
val CALL = "call"
|
||||
val MSGID = "msgid"
|
||||
val TYPE = "type"
|
||||
val TEXT = "text"
|
||||
lazy val TABLE_CREATE = """CREATE TABLE %s (%s INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
%s LONG, %s LONG,
|
||||
%s TEXT, %s TEXT,
|
||||
%s INTEGER, %s TEXT)"""
|
||||
.format(TABLE, _ID, TS, NEXTTS,
|
||||
CALL, MSGID,
|
||||
TYPE, TEXT)
|
||||
lazy val COLUMNS = Array(_ID, TS, NEXTTS, CALL, MSGID, TYPE, TEXT)
|
||||
}
|
||||
|
||||
var singleton : StorageDatabase = null
|
||||
|
|
|
@ -28,6 +28,10 @@ trait UIHelper extends Activity
|
|||
startActivity(new Intent(this, classOf[StationActivity]).putExtra("call", call))
|
||||
}
|
||||
|
||||
def openMessaging(call : String) {
|
||||
startActivity(new Intent(this, classOf[MessageActivity]).putExtra("call", call))
|
||||
}
|
||||
|
||||
def trackOnMap(call : String) {
|
||||
val text = getString(R.string.map_track_call, call)
|
||||
Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
|
||||
|
@ -260,6 +264,9 @@ trait UIHelper extends Activity
|
|||
case R.id.details =>
|
||||
openDetails(targetcall)
|
||||
true
|
||||
case R.id.message =>
|
||||
openMessaging(targetcall)
|
||||
true
|
||||
case R.id.mapbutton =>
|
||||
trackOnMap(targetcall)
|
||||
true
|
||||
|
|
Ładowanie…
Reference in New Issue