Skip to content

Commit 62e0664

Browse files
authored
Merge pull request #15 from scottlandis/master
Logger / viewer flavors
2 parents 138f3fe + ac58ea7 commit 62e0664

28 files changed

Lines changed: 556 additions & 752 deletions

torgi/build.gradle

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ android {
2626
// path "CMakeLists.txt"
2727
// }
2828
// }
29+
flavorDimensions "version"
30+
productFlavors {
31+
logger {
32+
dimension "version"
33+
applicationId "org.sofwerx.torgi.logger"
34+
versionNameSuffix "-logger"
35+
}
36+
viewer {
37+
dimension "version"
38+
applicationId "org.sofwerx.torgi.viewer"
39+
versionNameSuffix "-viewer"
40+
}
41+
}
42+
2943
compileOptions {
3044
targetCompatibility 1.8
3145
sourceCompatibility 1.8
@@ -36,11 +50,11 @@ dependencies {
3650
//implementation fileTree(include: ['*.jar'], dir: 'libs')
3751
//implementation project(':geopackage-sdk')
3852

39-
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' //for charts
40-
implementation 'org.osmdroid:osmdroid-android:6.0.2'
53+
viewerImplementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' //for charts
54+
viewerImplementation 'org.osmdroid:osmdroid-android:6.0.2'
4155
implementation 'mil.nga.geopackage:geopackage-android:3.0.2'
4256
implementation 'com.android.support:appcompat-v7:27.1.1'
43-
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
57+
viewerImplementation 'com.android.support.constraint:constraint-layout:1.1.3'
4458
//implementation 'com.google.android.gms:play-services-maps:15.0.1'
4559
implementation 'com.android.support:design:27.1.1'
4660
testImplementation 'junit:junit:4.12'
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.sofwerx.torgi.ui;
2+
3+
import android.os.Bundle;
4+
import android.widget.TextView;
5+
6+
import org.sofwerx.torgi.R;
7+
8+
public class MainActivity extends AbstractTORGIActivity {
9+
private TextView status;
10+
11+
@Override
12+
public void onCreate(Bundle savedInstanceState) {
13+
super.onCreate(savedInstanceState);
14+
status = findViewById(R.id.textView);
15+
}
16+
17+
@Override
18+
public void onResume() {
19+
super.onResume();
20+
if (permissionsPassed)
21+
status.setText(getString(R.string.notification));
22+
else
23+
status.setText(getString(R.string.torgi_not_running));
24+
}
25+
26+
@Override
27+
protected int getLayout() {
28+
return R.layout.activity_logger;
29+
}
30+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:layout_width="match_parent"
6+
android:layout_height="match_parent"
7+
android:orientation="vertical"
8+
tools:context=".ui.MainActivity">
9+
10+
<ImageView
11+
android:id="@+id/imageView"
12+
android:layout_width="80dp"
13+
android:layout_height="80dp"
14+
android:layout_centerInParent="true"
15+
android:src="@drawable/icon_gnns" />
16+
17+
<TextView
18+
android:id="@+id/textView"
19+
android:layout_width="wrap_content"
20+
android:layout_height="wrap_content"
21+
android:layout_below="@+id/imageView"
22+
android:layout_centerHorizontal="true"
23+
android:gravity="center"
24+
android:text="@string/torgi_not_running"
25+
android:textSize="20sp" />
26+
</RelativeLayout>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<resources>
2+
<string name="app_name">TORGI Logger</string>
3+
</resources>

torgi/src/main/AndroidManifest.xml

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
android:supportsRtl="true"
1515
android:theme="@style/AppTheme">
1616

17-
<meta-data
18-
android:name="com.google.android.geo.API_KEY"
19-
android:value="@string/google_maps_key" />
20-
2117
<service android:name="org.sofwerx.torgi.service.TorgiService"/>
2218

2319
<activity
@@ -27,15 +23,6 @@
2723
<action android:name="android.intent.action.MAIN" />
2824
<category android:name="android.intent.category.LAUNCHER" />
2925
</intent-filter>
30-
<!--android:theme="@style/AppTheme.NoActionBar">-->
31-
</activity>
32-
<activity
33-
android:name=".ui.MonitorActivity"
34-
android:label="TORGI Monitor">
35-
</activity>
36-
<activity
37-
android:name=".ui.AboutActivity"
38-
android:label="@string/about">
3926
</activity>
4027
</application>
4128
</manifest>
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
package org.sofwerx.torgi.ui;
2+
3+
import android.Manifest;
4+
import android.app.Activity;
5+
import android.app.AlertDialog;
6+
import android.content.ActivityNotFoundException;
7+
import android.content.ComponentName;
8+
import android.content.Context;
9+
import android.content.DialogInterface;
10+
import android.content.Intent;
11+
import android.content.ServiceConnection;
12+
import android.content.SharedPreferences;
13+
import android.content.pm.PackageManager;
14+
import android.location.Location;
15+
import android.net.Uri;
16+
import android.os.Build;
17+
import android.os.Bundle;
18+
import android.os.IBinder;
19+
import android.os.PowerManager;
20+
import android.preference.PreferenceManager;
21+
import android.provider.Settings;
22+
import android.support.v4.app.ActivityCompat;
23+
import android.support.v4.content.ContextCompat;
24+
import android.util.Log;
25+
import android.widget.Toast;
26+
27+
import org.sofwerx.torgi.R;
28+
import org.sofwerx.torgi.gnss.LatLng;
29+
import org.sofwerx.torgi.listener.GnssMeasurementListener;
30+
import org.sofwerx.torgi.service.TorgiService;
31+
32+
import java.util.ArrayList;
33+
34+
public abstract class AbstractTORGIActivity extends Activity {
35+
protected static final int REQUEST_DISABLE_BATTERY_OPTIMIZATION = 401;
36+
protected final static String TAG = "TORGI.monitor";
37+
private final static String PREF_BATTERY_OPT_IGNORE = "nvroptbat";
38+
private final static int PERM_REQUEST_CODE = 1;
39+
private boolean serviceBound = false;
40+
private TorgiService torgiService = null;
41+
protected boolean permissionsPassed = false;
42+
43+
protected void onCreate(Bundle savedInstanceState) {
44+
super.onCreate(savedInstanceState);
45+
setContentView(getLayout());
46+
permissionsPassed = checkPermissions();
47+
if (permissionsPassed)
48+
startService();
49+
openBatteryOptimizationDialogIfNeeded();
50+
};
51+
52+
protected abstract int getLayout();
53+
54+
@Override
55+
public void onResume() {
56+
super.onResume();
57+
if (this instanceof GnssMeasurementListener) {
58+
if (serviceBound && (torgiService != null))
59+
torgiService.setListener((GnssMeasurementListener)this);
60+
}
61+
}
62+
63+
@Override
64+
public void onPause() {
65+
if (torgiService != null)
66+
torgiService.setListener(null);
67+
super.onPause();
68+
}
69+
70+
@Override
71+
public void onStop() {
72+
super.onStop();
73+
if (serviceBound && (torgiService != null)) {
74+
try {
75+
unbindService(mConnection);
76+
} catch (Exception e) {
77+
e.printStackTrace();
78+
}
79+
}
80+
}
81+
82+
protected ServiceConnection mConnection = new ServiceConnection() {
83+
@Override
84+
public void onServiceConnected(ComponentName className, IBinder service) {
85+
Log.d(TAG,"MdxService bound to this activity");
86+
TorgiService.TorgiBinder binder = (TorgiService.TorgiBinder) service;
87+
torgiService = binder.getService();
88+
serviceBound = true;
89+
onTorgiServiceConnected();
90+
}
91+
92+
@Override
93+
public void onServiceDisconnected(ComponentName arg0) {
94+
serviceBound = false;
95+
}
96+
};
97+
98+
private void onTorgiServiceConnected() {
99+
if (this instanceof GnssMeasurementListener)
100+
torgiService.setListener((GnssMeasurementListener)this);
101+
}
102+
103+
private void startService() {
104+
if (serviceBound)
105+
torgiService.start();
106+
else {
107+
startService(new Intent(this, TorgiService.class));
108+
Intent intent = new Intent(this, TorgiService.class);
109+
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
110+
}
111+
}
112+
113+
/**
114+
* Request battery optimization exception so that the system doesn't throttle back our app
115+
*/
116+
private void openBatteryOptimizationDialogIfNeeded() {
117+
if (isOptimizingBattery() && isAllowAskAboutBattery()) {
118+
AlertDialog.Builder builder = new AlertDialog.Builder(this);
119+
builder.setTitle(R.string.enable_battery_optimization);
120+
builder.setMessage(R.string.battery_optimizations_narrative);
121+
builder.setPositiveButton(R.string.battery_optimize_yes, (dialog, which) -> {
122+
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
123+
Uri uri = Uri.parse("package:" + getPackageName());
124+
intent.setData(uri);
125+
try {
126+
startActivityForResult(intent, REQUEST_DISABLE_BATTERY_OPTIMIZATION);
127+
} catch (ActivityNotFoundException e) {
128+
Toast.makeText(this, R.string.does_not_support_battery_optimization, Toast.LENGTH_SHORT).show();
129+
}
130+
});
131+
builder.setOnDismissListener(dialog -> setNeverAskBatteryOptimize());
132+
final AlertDialog dialog = builder.create();
133+
dialog.setCanceledOnTouchOutside(false);
134+
dialog.show();
135+
}
136+
}
137+
138+
protected boolean isOptimizingBattery() {
139+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
140+
final PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
141+
return pm != null && !pm.isIgnoringBatteryOptimizations(getPackageName());
142+
} else
143+
return false;
144+
}
145+
146+
private boolean isAllowAskAboutBattery() {
147+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
148+
return !prefs.getBoolean(PREF_BATTERY_OPT_IGNORE,false);
149+
}
150+
151+
private void setNeverAskBatteryOptimize() {
152+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
153+
SharedPreferences.Editor edit = prefs.edit();
154+
edit.putBoolean(PREF_BATTERY_OPT_IGNORE,true);
155+
edit.apply();
156+
}
157+
158+
@Override
159+
public void onActivityResult(int requestCode, int resultCode, final Intent data) {
160+
super.onActivityResult(requestCode, resultCode, data);
161+
switch (requestCode) {
162+
case REQUEST_DISABLE_BATTERY_OPTIMIZATION:
163+
setNeverAskBatteryOptimize();
164+
break;
165+
}
166+
}
167+
168+
@Override
169+
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
170+
if (requestCode == PERM_REQUEST_CODE) {
171+
if (checkPermissions()) {
172+
permissionsPassed = true;
173+
startService();
174+
} else {
175+
Toast.makeText(this, "Both Location and Storage permissions are needed", Toast.LENGTH_LONG).show();
176+
}
177+
}
178+
}
179+
180+
/**
181+
* Returns true once all required permissions are granted, otherwise returns false and requests the
182+
* required permission
183+
* @return
184+
*/
185+
private boolean checkPermissions() {
186+
ArrayList<String> needed = new ArrayList<>();
187+
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
188+
needed.add(Manifest.permission.ACCESS_FINE_LOCATION);
189+
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
190+
needed.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
191+
if (needed.isEmpty())
192+
return true;
193+
else {
194+
String[] perms = new String[needed.size()];
195+
perms = new String[perms.length];
196+
for (int i=0;i<perms.length;i++) {
197+
perms[i] = needed.get(i);
198+
}
199+
ActivityCompat.requestPermissions(this, perms, PERM_REQUEST_CODE);
200+
return false;
201+
}
202+
}
203+
204+
@Override
205+
public void onBackPressed() {
206+
new AlertDialog.Builder(this)
207+
.setTitle(R.string.quit_torgi)
208+
.setMessage(R.string.quit_torgi_narrative)
209+
.setNegativeButton(R.string.quit_yes, new DialogInterface.OnClickListener() {
210+
@Override
211+
public void onClick(DialogInterface dialog, int which) {
212+
if (serviceBound && (torgiService != null))
213+
torgiService.shutdown();
214+
AbstractTORGIActivity.this.finish();
215+
}
216+
})
217+
.setPositiveButton(R.string.quit_run_in_background, new DialogInterface.OnClickListener() {
218+
public void onClick(DialogInterface arg0, int arg1) {
219+
AbstractTORGIActivity.this.finish();
220+
}
221+
}).create().show();
222+
}
223+
}

0 commit comments

Comments
 (0)