Porównaj commity

...

22 Commity

Autor SHA1 Wiadomość Data
Georg Lukas d38a0dae39 USB: fix read-only permission intent crash, thx M0JMO 2024-04-03 22:20:24 +02:00
Georg Lukas 7ede1c26fc Android 13+: ask for Post Notification permission 2024-01-21 17:25:01 +01:00
Georg Lukas 73af9d1c5d Android before 12: fix Bluetooth connect permissions 2024-01-07 15:16:36 +01:00
Georg Lukas 4e2788e6b3 Permissions: (repeatedly) show permissions dialog 2023-10-10 09:56:20 +02:00
Georg Lukas 2ac1d3f1e6 Prefs: immediately ask for required permissions, needed for BT device list 2023-10-10 09:53:41 +02:00
Georg Lukas e3cb376195 Android 13: Bluetooth connect permission 2023-10-10 09:52:55 +02:00
Georg Lukas aee35ed3ed XXX OSM: do not check permissions immediately 2023-10-08 20:22:04 +02:00
Georg Lukas b8ff35560e VTM refactor: split Station class for OSM/other uses 2023-10-08 20:22:04 +02:00
Georg Lukas 4c6a8a1b3f Permissions: rework failure dialog 2023-10-08 20:22:04 +02:00
Georg Lukas 03e4a36d61 Android 13: bump SDK 2023-10-08 20:22:04 +02:00
Georg Lukas 06fc910b9d Android 13: pending intents in backend code 2023-10-08 20:22:04 +02:00
Georg Lukas 70462b73d7 Android 13: mark pending intents immutable 2023-10-08 20:22:04 +02:00
Georg Lukas 23833b55ef Android 13: request coarse+fine location (effect untested) 2023-10-08 20:22:04 +02:00
Georg Lukas 6751f24750 Android 13: explicitly export activities 2023-10-08 20:22:04 +02:00
Georg Lukas 6607f3d027 USBSerial: update USB IDs 2023-10-08 20:22:04 +02:00
Georg Lukas e669116795 r30 HACK: broken file fetch dialog, no way to fix for v3 mapsforge lib 2023-10-08 20:22:04 +02:00
Georg Lukas 08b4e7293e proguard: fix extends/implements warning 2023-10-08 19:19:12 +02:00
Georg Lukas 2ac0d739ae OSM: do not crash on online/offline race condition 2022-10-17 15:21:21 +02:00
Georg Lukas 734498c6e0 Android 11: work around r30 limitations for APK build 2022-02-08 19:25:09 +01:00
Georg Lukas 5e7c8fc0e3 Map: always show keyboard help in coordinate chooser 2022-02-08 19:24:57 +01:00
Georg Lukas 11d1e63299 Map: fix coordinate chooser display and saving 2022-02-08 19:08:17 +01:00
Georg Lukas 106edf8b90 OSM: show error from map loader 2022-02-08 18:58:43 +01:00
17 zmienionych plików z 161 dodań i 70 usunięć

Wyświetl plik

@ -11,13 +11,16 @@
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.usb.host" android:required="false" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
@ -27,6 +30,7 @@
<application android:label="@string/app_name" android:icon="@drawable/icon"
android:name=".APRSdroidApplication"
android:usesCleartextTraffic="true"
android:requestLegacyExternalStorage="true"
android:allowBackup="true"
android:theme="@style/DefaultTheme" >
@ -36,7 +40,8 @@
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
<activity android:name=".APRSdroid"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name">
android:label="@string/app_name"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@ -94,13 +99,16 @@
android:launchMode="singleTop"
android:parentActivityName=".HubActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/MapViewTheme" >
android:theme="@style/MapViewTheme"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".ProfileImportActivity" android:label="@string/profile_import_activity">
<activity android:name=".ProfileImportActivity" android:label="@string/profile_import_activity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@ -120,7 +128,8 @@
android:pathPattern=".*\\.aprs" />
</intent-filter>
</activity>
<activity android:name=".KeyfileImportActivity" android:label="@string/ssl_import_activity">
<activity android:name=".KeyfileImportActivity" android:label="@string/ssl_import_activity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@ -149,7 +158,9 @@
</activity>
<service android:name=".AprsService" android:label="@string/aprsservice"
android:foregroundServiceType="location"
tools:ignore="ExportedService" >
tools:ignore="ExportedService"
android:exported="true"
>
<intent-filter>
<action android:name="org.aprsdroid.app.SERVICE" />
<action android:name="org.aprsdroid.app.ONCE" />
@ -159,7 +170,7 @@
</intent-filter>
</service>
<!-- start the service if applicable on boot -->
<receiver android:name=".SystemEventReceiver">
<receiver android:name=".SystemEventReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>

Wyświetl plik

@ -77,11 +77,11 @@ amazon {
}
android {
compileSdkVersion 30
buildToolsVersion "29.0.3"
compileSdkVersion 33
buildToolsVersion "33.0.2"
defaultConfig {
minSdkVersion 14
targetSdkVersion 30
targetSdkVersion 33
versionName "$build_revision"
versionCode versionCodeDate()
resValue "string", "build_revision", "$build_revision"

Wyświetl plik

@ -35,7 +35,7 @@
-keep public class com.jazzido.PacketDroid.AudioBufferProcessor {
public void callback(byte[]);
}
-keepclassmembers class * extends com.jazzido.PacketDroid.PacketCallback {
-keepclassmembers class * implements com.jazzido.PacketDroid.PacketCallback {
public void received(...);
}

Wyświetl plik

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- UsbSerial/usbserial/src/main$ perl -lne '/new ConcreteDevice ?.(0x[0-9a-f]{4}), (0x[0-9a-f]{4})/i && printf "\t<usb-device vendor-id=\"%d\" product-id=\"%d\" />\n", hex($1), hex($2)' java/com/felhr/deviceids/*.java -->
<!-- UsbSerial/usbserial/src/main$ perl -lne '/createDevice ?.(0x[0-9a-f]{4}), (0x[0-9a-f]{4})/i && printf "\t<usb-device vendor-id=\"%d\" product-id=\"%d\" />\n", hex($1), hex($2)' java/com/felhr/deviceids/*.java | sort -n -->
<usb-device vendor-id="17224" product-id="21795" />
<usb-device vendor-id="6790" product-id="29987" />
<usb-device vendor-id="6790" product-id="21795" />
@ -77,13 +77,17 @@
<usb-device vendor-id="4292" product-id="34296" />
<usb-device vendor-id="4292" product-id="34404" />
<usb-device vendor-id="4292" product-id="34405" />
<usb-device vendor-id="4292" product-id="34652" />
<usb-device vendor-id="4292" product-id="34980" />
<usb-device vendor-id="4292" product-id="34981" />
<usb-device vendor-id="4292" product-id="60000" />
<usb-device vendor-id="4292" product-id="60001" />
<usb-device vendor-id="4292" product-id="60003" />
<usb-device vendor-id="4292" product-id="60016" />
<usb-device vendor-id="4292" product-id="60032" />
<usb-device vendor-id="4292" product-id="60017" />
<usb-device vendor-id="4292" product-id="60026" />
<usb-device vendor-id="4292" product-id="60027" />
<usb-device vendor-id="4292" product-id="60032" />
<usb-device vendor-id="4292" product-id="61441" />
<usb-device vendor-id="4292" product-id="61442" />
<usb-device vendor-id="4292" product-id="61443" />
@ -136,6 +140,7 @@
<usb-device vendor-id="12693" product-id="62080" />
<usb-device vendor-id="12693" product-id="62081" />
<usb-device vendor-id="16700" product-id="38144" />
<usb-device vendor-id="6408" product-id="8977" />
<usb-device vendor-id="4292" product-id="34720" />
<usb-device vendor-id="1027" product-id="24577" />
<usb-device vendor-id="1027" product-id="24582" />
@ -373,7 +378,6 @@
<usb-device vendor-id="1003" product-id="8457" />
<usb-device vendor-id="1110" product-id="61440" />
<usb-device vendor-id="1110" product-id="61441" />
<usb-device vendor-id="1240" product-id="10" />
<usb-device vendor-id="1412" product-id="45088" />
<usb-device vendor-id="1607" product-id="256" />
<usb-device vendor-id="1742" product-id="33553" />
@ -734,6 +738,8 @@
<usb-device vendor-id="2915" product-id="25904" />
<usb-device vendor-id="2956" product-id="8963" />
<usb-device vendor-id="4362" product-id="4432" />
<usb-device vendor-id="1367" product-id="8200" />
<usb-device vendor-id="9805" product-id="562" />
<usb-device vendor-id="9805" product-id="288" />
<usb-device vendor-id="1155" product-id="22336" />
</resources>

Wyświetl plik

@ -12,6 +12,9 @@ import android.widget.Toast
class BackendPrefs extends PreferenceActivity
with OnSharedPreferenceChangeListener
with PermissionHelper {
val BACKEND_PERMISSION = 1000
def loadXml() {
val prefs = new PrefsWrapper(this)
addPreferencesFromResource(R.xml.backend)
@ -22,6 +25,10 @@ class BackendPrefs extends PreferenceActivity
hookPasscode()
hookGpsPermission()
}
val perms = AprsBackend.defaultBackendPermissions(prefs)
if (perms.nonEmpty) {
checkPermissions(perms.toArray, BACKEND_PERMISSION)
}
}
def hookPasscode(): Unit = {
@ -42,7 +49,7 @@ class BackendPrefs extends PreferenceActivity
def onPreferenceClick(preference: Preference) = {
if (preference.asInstanceOf[CheckBoxPreference].isChecked) {
preference.asInstanceOf[CheckBoxPreference].setChecked(false)
checkPermissions(Array(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_GPS)
checkPermissions(Array(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), REQUEST_GPS)
}
true
}
@ -71,6 +78,13 @@ class BackendPrefs extends PreferenceActivity
override def getActionName(action: Int): Int = R.string.p_conn_kwd_gps
override def onAllPermissionsGranted(action: Int): Unit = {
findPreference("kenwood.gps").asInstanceOf[CheckBoxPreference].setChecked(true)
action match {
case REQUEST_GPS =>
findPreference("kenwood.gps").asInstanceOf[CheckBoxPreference].setChecked(true)
case _ =>
}
}
override def onPermissionsFailedCancel(action: Int): Unit = {
// nop
}
}

Wyświetl plik

@ -41,7 +41,7 @@ class LocationPrefs extends PreferenceActivity with OnSharedPreferenceChangeList
if (i != null && i.getDataString() != null) {
i.getDataString() match {
case "gps2manual" =>
checkPermissions(Array(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_GPS)
checkPermissions(Array(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), REQUEST_GPS)
case "chooseOnMap" =>
val mapmode = MapModes.defaultMapMode(this, prefs)
startActivityForResult(new Intent(this, mapmode.viewClass).putExtra("info", R.string.p_source_from_map_save), REQUEST_MAP)
@ -72,4 +72,7 @@ class LocationPrefs extends PreferenceActivity with OnSharedPreferenceChangeList
pe.commit()
} else Toast.makeText(this, getString(R.string.map_track_unknown, prefs.getCallsign()), Toast.LENGTH_SHORT).show()
}
override def onPermissionsFailedCancel(action: Int): Unit = {
// nop
}
}

Wyświetl plik

@ -19,8 +19,10 @@ import _root_.org.mapsforge.v3.android.maps.overlay.{ItemizedOverlay, OverlayIte
import _root_.scala.collection.mutable.ArrayBuffer
import _root_.java.io.File
import _root_.java.util.ArrayList
import java.lang.UnsupportedOperationException
import org.mapsforge.v3.android.maps.mapgenerator.{MapGeneratorFactory, MapGeneratorInternal}
import org.mapsforge.v3.map.reader.header.FileOpenResult
// to make scala-style iterating over arraylist possible
import scala.collection.JavaConversions._
@ -35,7 +37,7 @@ class MapAct extends MapActivity with MapMenuHelper {
lazy val db = StorageDatabase.open(this)
lazy val staoverlay = new StationOverlay(allicons, this, db)
lazy val loading = findViewById(R.id.loading).asInstanceOf[View]
lazy val locReceiver = new LocationReceiver2[ArrayList[Station]](staoverlay.load_stations,
lazy val locReceiver = new LocationReceiver2[ArrayList[OSMStation]](staoverlay.load_stations,
staoverlay.replace_stations, staoverlay.cancel_stations)
override def onCreate(savedInstanceState: Bundle) {
@ -51,13 +53,16 @@ class MapAct extends MapActivity with MapMenuHelper {
override def onResume() {
super.onResume()
// only make it default if not tracking
if (targetcall == "")
if (isCoordinateChooser)
setTitle(R.string.p_source_from_map)
else if (targetcall == "")
makeLaunchActivity("map")
else
setLongTitle(R.string.app_map, targetcall)
setKeepScreenOn()
setVolumeControls()
checkPermissions(Array(Manifest.permission.WRITE_EXTERNAL_STORAGE), RELOAD_MAP)
//checkPermissions(Array(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE), RELOAD_MAP)
reloadMapAndTheme()
mapview.requestFocus()
}
@ -105,26 +110,39 @@ class MapAct extends MapActivity with MapMenuHelper {
}
}
override def onPermissionsFailed(action: Int, permissions: Set[String]): Unit = {
if (action == RELOAD_MAP) {
if (targetcall == "")
startActivity(new Intent(this, classOf[HubActivity]).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
finish()
}
super.onPermissionsFailed(action, permissions)
}
override def onPermissionsFailed(action : Int, permissions : Set[String]): Unit = {
// fail to online OSM map
}
override def onPermissionsFailedCancel(action: Int): Unit = {
// should never be called
}
def reloadMapAndTheme() {
val mapfile = new File(prefs.getString("mapfile", android.os.Environment.getExternalStorageDirectory() + "/aprsdroid.map"))
if (mapfile.exists() && mapfile.canRead())
mapview.setMapFile(mapfile)
else {
if (prefs.getString("mapfile", null) != null)
Toast.makeText(this, getString(R.string.mapfile_error, mapfile), Toast.LENGTH_SHORT).show()
val map_source = MapGeneratorInternal.MAPNIK
val map_gen = new OsmTileDownloader()
map_gen.setUserAgent(getString(R.string.build_version))
mapview.setMapGenerator(map_gen)
var error = if (mapfile.exists() && mapfile.canRead()) {
val result = mapview.setMapFile(mapfile)
// output map loader's error if loading failed
if (result.isSuccess) null else result.getErrorMessage
} else if (prefs.getString("mapfile", null) != null) {
// output generic error if file was configured but is not loadable
getString(R.string.mapfile_error, mapfile)
} else {
// do not output error if no map file was configured, silently load online osm
null
}
if (error != null)
Toast.makeText(this, error, Toast.LENGTH_SHORT).show()
// all map file attempts failed, fall back to online
try {
if (mapview.getMapFile == null) {
val map_source = MapGeneratorInternal.MAPNIK
val map_gen = new OsmTileDownloader()
map_gen.setUserAgent(getString(R.string.build_version))
mapview.setMapGenerator(map_gen)
}
} catch {
case _ : UnsupportedOperationException => /* ignore, this is thrown by online map generator */
}
val themefile = new File(prefs.getString("themefile", android.os.Environment.getExternalStorageDirectory() + "/aprsdroid.xml"))
if (themefile.exists())
@ -153,6 +171,7 @@ class MapAct extends MapActivity with MapMenuHelper {
KeyEvent.KEYCODE_ENTER =>
// TODO: return coordinates
if (isCoordinateChooser) {
setResult(android.app.Activity.RESULT_OK, resultIntent)
finish()
}
true
@ -201,7 +220,7 @@ class MapAct extends MapActivity with MapMenuHelper {
}
}
class Station(val movelog : ArrayBuffer[GeoPoint], val pt : GeoPoint,
class OSMStation(val movelog : ArrayBuffer[GeoPoint], val pt : GeoPoint,
val call : String, val origin : String, val symbol : String)
extends OverlayItem(pt, call, origin) {
@ -215,11 +234,11 @@ class Station(val movelog : ArrayBuffer[GeoPoint], val pt : GeoPoint,
}
}
class StationOverlay(icons : Drawable, context : MapAct, db : StorageDatabase) extends ItemizedOverlay[Station](icons) {
class StationOverlay(icons : Drawable, context : MapAct, db : StorageDatabase) extends ItemizedOverlay[OSMStation](icons) {
val TAG = "APRSdroid.StaOverlay"
//lazy val calls = new scala.collection.mutable.HashMap[String, Boolean]()
var stations = new java.util.ArrayList[Station]()
var stations = new java.util.ArrayList[OSMStation]()
// prevent android bug #11666
populate()
@ -231,7 +250,7 @@ class StationOverlay(icons : Drawable, context : MapAct, db : StorageDatabase) e
icons.setBounds(0, 0, symbolSize, symbolSize)
override def size() = stations.size()
override def createItem(idx : Int) : Station = stations.get(idx)
override def createItem(idx : Int) : OSMStation = stations.get(idx)
def symbol2rect(index : Int, page : Int) : Rect = {
// check for overflow
@ -250,7 +269,7 @@ class StationOverlay(icons : Drawable, context : MapAct, db : StorageDatabase) e
(symbol(0) != '/' && symbol(0) != '\\')
}
def drawTrace(c : Canvas, proj : Projection, s : Station) : Unit = {
def drawTrace(c : Canvas, proj : Projection, s : OSMStation) : Unit = {
//Log.d(TAG, "drawing trace of %s".format(call))
val tracePaint = new Paint()
@ -339,7 +358,7 @@ class StationOverlay(icons : Drawable, context : MapAct, db : StorageDatabase) e
context.handler.post { context.updateCoordinateInfo() }
}
def addStation(sta : Station) {
def addStation(sta : OSMStation) {
//if (calls.contains(sta.getTitle()))
// return
//calls.add(sta.getTitle(), true)
@ -407,10 +426,10 @@ class StationOverlay(icons : Drawable, context : MapAct, db : StorageDatabase) e
m
}
def load_stations(i : Intent) : ArrayList[Station] = {
def load_stations(i : Intent) : ArrayList[OSMStation] = {
import StorageDatabase.Station._
val s = new ArrayList[Station]()
val s = new ArrayList[OSMStation]()
val age_ts = (System.currentTimeMillis - context.prefs.getShowAge()).toString
val filter = if (context.showObjects) "TS > ? OR CALL=?" else "(ORIGIN IS NULL AND TS > ?) OR CALL=?"
val c = db.getStations(filter, Array(age_ts, context.targetcall), null)
@ -425,7 +444,7 @@ class StationOverlay(icons : Drawable, context : MapAct, db : StorageDatabase) e
val origin = c.getString(COLUMN_MAP_ORIGIN)
val p = new GeoPoint(lat, lon)
val m = fetchStaPositions(call, pos_c)
s.add(new Station(m, p, call, origin, symbol))
s.add(new OSMStation(m, p, call, origin, symbol))
c.moveToNext()
}
c.close()
@ -434,12 +453,12 @@ class StationOverlay(icons : Drawable, context : MapAct, db : StorageDatabase) e
s
}
def replace_stations(s : ArrayList[Station]) {
def replace_stations(s : ArrayList[OSMStation]) {
stations = s
Benchmark("populate") { populate() }
context.onPostLoad()
}
def cancel_stations(s : ArrayList[Station]) {
def cancel_stations(s : ArrayList[OSMStation]) {
}
}

Wyświetl plik

@ -24,7 +24,14 @@ trait MapLoaderBase extends MapMenuHelper {
super.onDestroy()
}
def onStationUpdate(sl : ArrayList[Station])
def newStation(call : String, origin : String, symbol : String,
lat : Double, lon : Double,
qrg : String, comment : String, speed : Int, course : Int,
movelog : ArrayBuffer[Point]) : Station = {
new Station(call, origin, symbol, lat, lon, qrg, comment, speed, course, movelog)
}
def onStationUpdate(sl : ArrayList[Station])
def startLoading() {
locReceiver.startTask(null)
@ -52,7 +59,7 @@ trait MapLoaderBase extends MapMenuHelper {
val cse = c.getInt(COLUMN_MAP_CSE)
if (call != null && !call.isEmpty)
s.add(new Station(call, origin, symbol, lat/1000000.0d, lon/1000000.0d,
s.add(newStation(call, origin, symbol, lat/1000000.0d, lon/1000000.0d,
qrg, comment, speed, cse,
null))
c.moveToNext()

Wyświetl plik

@ -46,7 +46,7 @@ trait MapMenuHelper extends UIHelper with OnClickListener {
infoText.setVisibility(View.INVISIBLE)
accept.setVisibility(View.INVISIBLE)
}
keyboardNavDialog()
keyboardNavDialog(isCoordinateChooser)
}
abstract override def onCreateOptionsMenu(menu : Menu) : Boolean = {

Wyświetl plik

@ -10,6 +10,7 @@ import android.provider.Settings
trait PermissionHelper extends Activity {
def getActionName(action : Int): Int
def onAllPermissionsGranted(action : Int): Unit
def onPermissionsFailedCancel(action : Int): Unit
def checkPermissions(permissions : Array[String], action : Int): Boolean = {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@ -71,7 +72,11 @@ trait PermissionHelper extends Activity {
startActivity(intent)
}
})
.setNegativeButton(android.R.string.cancel, null)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener {
override def onClick(dialogInterface: DialogInterface, i: Int): Unit = {
onPermissionsFailedCancel(action)
}
})
.create().show()
}

Wyświetl plik

@ -40,7 +40,7 @@ class PrefsAct extends PreferenceActivity {
def fileChooserPreference(pref_name : String, reqCode : Int, titleId : Int) {
findPreference(pref_name).setOnPreferenceClickListener(new OnPreferenceClickListener() {
def onPreferenceClick(preference : Preference) = {
val get_file = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*")
val get_file = new Intent(Intent.ACTION_OPEN_DOCUMENT).setType("*/*")
startActivityForResult(Intent.createChooser(get_file,
getString(titleId)), reqCode)
true
@ -110,7 +110,13 @@ class PrefsAct extends PreferenceActivity {
override def onActivityResult(reqCode : Int, resultCode : Int, data : Intent) {
android.util.Log.d("PrefsAct", "onActResult: request=" + reqCode + " result=" + resultCode + " " + data)
if (resultCode == android.app.Activity.RESULT_OK && reqCode == 123456) {
parseFilePickerResult(data, "mapfile", R.string.mapfile_error)
//parseFilePickerResult(data, "mapfile", R.string.mapfile_error)
val takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
getContentResolver.takePersistableUriPermission(data.getData(), takeFlags)
PreferenceManager.getDefaultSharedPreferences(this)
.edit().putString("mapfile", data.getDataString()).commit()
finish()
startActivity(getIntent())
} else
if (resultCode == android.app.Activity.RESULT_OK && reqCode == 123457) {
parseFilePickerResult(data, "themefile", R.string.themefile_error)
@ -129,7 +135,7 @@ class PrefsAct extends PreferenceActivity {
override def onOptionsItemSelected(mi : MenuItem) : Boolean = {
mi.getItemId match {
case R.id.profile_load =>
val get_file = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*")
val get_file = new Intent(Intent.ACTION_OPEN_DOCUMENT).setType("*/*")
// TODO: use MaterialFilePicker().withFilter() for *.aprs
startActivityForResult(Intent.createChooser(get_file,
getString(R.string.profile_import_activity)), 123458)

Wyświetl plik

@ -41,7 +41,7 @@ class ServiceNotifier {
val nb = newNotificationBuilder(ctx, "status")
.setContentTitle(appname)
.setContentText(status)
.setContentIntent(PendingIntent.getActivity(ctx, 0, i, 0))
.setContentIntent(PendingIntent.getActivity(ctx, 0, i, PendingIntent.FLAG_IMMUTABLE))
.setSmallIcon(R.drawable.ic_status)
.setWhen(System.currentTimeMillis)
.setOngoing(true)
@ -68,7 +68,7 @@ class ServiceNotifier {
newNotificationBuilder(ctx, "msg")
.setContentTitle(call)
.setContentText(message)
.setContentIntent(PendingIntent.getActivity(ctx, 0, i, PendingIntent.FLAG_UPDATE_CURRENT))
.setContentIntent(PendingIntent.getActivity(ctx, 0, i, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
.setSmallIcon(R.drawable.icon)
.setTicker(call + ": " + message)
.setWhen(System.currentTimeMillis)

Wyświetl plik

@ -108,6 +108,9 @@ trait UIHelper extends Activity
case START_SERVICE_ONCE => startService(AprsService.intent(this, AprsService.SERVICE_ONCE))
}
}
override def onPermissionsFailedCancel(action: Int): Unit = {
// nop
}
def startAprsService(action : Int): Unit = {
checkPermissions(currentListOfPermissions(), action)
}
@ -137,20 +140,22 @@ trait UIHelper extends Activity
passcodeDialog.show()
}
def keyboardNavDialog() {
def keyboardNavDialog(force : Boolean = false) {
if (getPackageManager().hasSystemFeature("android.hardware.touchscreen"))
return
if (prefs.getBoolean("kbdnav_shown", false))
if (!force && prefs.getBoolean("kbdnav_shown", false))
return
prefs.prefs.edit().putBoolean("kbdnav_shown", true).commit()
val keys = Array("⬅➡⬆⬇", "⏪⏩", "⏯️", "⏎🆗")
val keys = Array("←→↑↓", "⏪⏩", "⏯️", "⏎🆗")
val titles = getResources().getStringArray(R.array.kbdnav_lines)
val text = keys zip titles map { case (k, v) => "%s\t%s".format(k, v) } mkString("\n")
val text = keys zip titles map { case (k, v) => "%s\t%s".format(k, v) } mkString("\n\n")
new AlertDialog.Builder(this).setTitle(R.string.kbdnav_title)
.setMessage(text)
.setIcon(android.R.drawable.ic_dialog_info)
.setPositiveButton(android.R.string.ok, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener {
override def onClick(dialog: DialogInterface, which: Int) = {
prefs.prefs.edit().putBoolean("kbdnav_shown", true).commit()
}})
.create.show
}

Wyświetl plik

@ -1,6 +1,7 @@
package org.aprsdroid.app
import android.Manifest
import android.os.Build
import _root_.net.ab0oo.aprs.parser.APRSPacket
import _root_.java.io.{InputStream, OutputStream}
@ -32,6 +33,12 @@ object AprsBackend {
val need_passcode : Int
) {}
val BLUETOOTH_PERMISSION = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Manifest.permission.BLUETOOTH_CONNECT
} else {
Manifest.permission.BLUETOOTH_ADMIN
}
// map from old "backend" to new proto-link-aprsis (defaults are bluetooth and tcp)
val backend_upgrade = Map(
"tcp" -> "aprsis-tcpip-tcp",
@ -61,7 +68,7 @@ object AprsBackend {
"afsk" -> new BackendInfo(
(s, p) => new AfskUploader(s, p),
0,
Set(Manifest.permission.RECORD_AUDIO),
Set(Manifest.permission.RECORD_AUDIO),
CAN_DUPLEX,
PASSCODE_NONE),
"tcp" -> new BackendInfo(
@ -73,7 +80,7 @@ object AprsBackend {
"bluetooth" -> new BackendInfo(
(s, p) => new BluetoothTnc(s, p),
R.xml.backend_bluetooth,
Set(Manifest.permission.BLUETOOTH_ADMIN),
Set(BLUETOOTH_PERMISSION),
CAN_DUPLEX,
PASSCODE_NONE),
"tcpip" -> new BackendInfo(
@ -134,7 +141,10 @@ object AprsBackend {
val perms = scala.collection.mutable.Set[String]()
perms ++= AprsBackend.defaultBackendInfo(prefs).permissions
if (prefs.getProto() == "kenwood" && prefs.getBoolean("kenwood.gps", false))
perms.add(Manifest.permission.ACCESS_FINE_LOCATION)
perms += (Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
perms += (Manifest.permission.POST_NOTIFICATIONS)
}
perms.toSet
}

Wyświetl plik

@ -49,7 +49,7 @@ class UsbTnc(service : AprsService, prefs : PrefsWrapper) extends AprsBackend(pr
var alreadyRunning = false
val intent = new Intent(USB_PERM_ACTION)
val pendingIntent = PendingIntent.getBroadcast(service, 0, intent, 0)
val pendingIntent = PendingIntent.getBroadcast(service, 0, intent, PendingIntent.FLAG_MUTABLE)
val receiver = new BroadcastReceiver() {
override def onReceive(ctx : Context, i : Intent) {
@ -59,6 +59,11 @@ class UsbTnc(service : AprsService, prefs : PrefsWrapper) extends AprsBackend(pr
ctx.stopService(AprsService.intent(ctx, AprsService.SERVICE))
return
}
if (i.getExtras() == null) {
/* this shouldn't ever happen, don't need i18n */
service.postAbort("USB permission bug")
return
}
val granted = i.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED)
if (!granted) {
service.postAbort(service.getString(R.string.p_serial_noperm))

Wyświetl plik

@ -16,7 +16,7 @@ class FixedPosition(service : AprsService, prefs : PrefsWrapper) extends Locatio
val intent = new Intent(ALARM_ACTION)
val pendingIntent = PendingIntent.getBroadcast(service, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT)
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)
// get called on alarm
val receiver = new BroadcastReceiver() {

Wyświetl plik

@ -22,8 +22,8 @@ object LocationSource {
}
def getPermissions(prefs : PrefsWrapper) = {
prefs.getString("loc_source", DEFAULT_CONNTYPE) match {
case "smartbeaconing" => Set(Manifest.permission.ACCESS_FINE_LOCATION)
case "periodic" => Set(Manifest.permission.ACCESS_FINE_LOCATION)
case "smartbeaconing" => Set(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
case "periodic" => Set(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
case "manual" => Set()
}
}