560 lines
20 KiB
Java
560 lines
20 KiB
Java
package btools.routingapp;
|
|
|
|
import static btools.routingapp.BInstallerView.MASK_CURRENT_RD5;
|
|
import static btools.routingapp.BInstallerView.MASK_DELETED_RD5;
|
|
import static btools.routingapp.BInstallerView.MASK_INSTALLED_RD5;
|
|
import static btools.routingapp.BInstallerView.MASK_SELECTED_RD5;
|
|
|
|
import android.Manifest;
|
|
import android.annotation.SuppressLint;
|
|
import android.app.AlertDialog;
|
|
import android.app.Dialog;
|
|
import android.content.DialogInterface;
|
|
import android.content.pm.PackageManager;
|
|
import android.content.res.Resources;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.text.format.Formatter;
|
|
import android.util.Log;
|
|
import android.view.View;
|
|
import android.widget.Button;
|
|
import android.widget.TextView;
|
|
import android.widget.Toast;
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.core.app.ActivityCompat;
|
|
import androidx.core.content.ContextCompat;
|
|
import androidx.lifecycle.LiveData;
|
|
import androidx.work.Constraints;
|
|
import androidx.work.Data;
|
|
import androidx.work.ExistingWorkPolicy;
|
|
import androidx.work.NetworkType;
|
|
import androidx.work.OneTimeWorkRequest;
|
|
import androidx.work.WorkInfo;
|
|
import androidx.work.WorkManager;
|
|
|
|
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
|
import com.google.common.util.concurrent.ListenableFuture;
|
|
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.concurrent.ExecutionException;
|
|
|
|
import btools.router.RoutingHelper;
|
|
|
|
public class BInstallerActivity extends AppCompatActivity {
|
|
|
|
private static final int DIALOG_CONFIRM_DELETE_ID = 1;
|
|
private static final int DIALOG_CONFIRM_NEXTSTEPS_ID = 2;
|
|
private static final int DIALOG_CONFIRM_GETDIFFS_ID = 3;
|
|
private static final int DIALOG_NEW_APP_NEEDED_ID = 4;
|
|
|
|
public static final int MY_PERMISSIONS_REQUEST_NITIFICATION = 100;
|
|
|
|
public static boolean downloadCanceled = false;
|
|
private File mBaseDir;
|
|
private BInstallerView mBInstallerView;
|
|
private Button mButtonDownload;
|
|
private TextView mSummaryInfo;
|
|
private TextView mDownloadSummaryInfo;
|
|
private LinearProgressIndicator mProgressIndicator;
|
|
private ArrayList<Integer> selectedTiles;
|
|
|
|
BInstallerView.OnSelectListener onSelectListener;
|
|
|
|
@SuppressLint("UsableSpace")
|
|
public static long getAvailableSpace(String baseDir) {
|
|
File f = new File(baseDir);
|
|
if (!f.exists()) return 0L;
|
|
return f.getUsableSpace();
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
boolean running = isDownloadRunning(DownloadWorker.class);
|
|
|
|
setContentView(R.layout.activity_binstaller);
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
|
|
== PackageManager.PERMISSION_GRANTED) {
|
|
// nothing to do
|
|
} else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
|
|
//
|
|
} else {
|
|
// You can directly ask for the permission.
|
|
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, MY_PERMISSIONS_REQUEST_NITIFICATION);
|
|
}
|
|
}
|
|
|
|
mSummaryInfo = findViewById(R.id.textViewSegmentSummary);
|
|
mBInstallerView = findViewById(R.id.BInstallerView);
|
|
onSelectListener = new BInstallerView.OnSelectListener() {
|
|
@Override
|
|
public void onSelect() {
|
|
//if (!isDownloadRunning(DownloadWorker.class))
|
|
updateDownloadButton();
|
|
}
|
|
};
|
|
|
|
mBInstallerView.setOnSelectListener(onSelectListener);
|
|
|
|
mButtonDownload = findViewById(R.id.buttonDownload);
|
|
mButtonDownload.setOnClickListener(
|
|
view -> {
|
|
if (isDownloadRunning(DownloadWorker.class)) {
|
|
stopDownload();
|
|
} else if (mBInstallerView.getSelectedTiles(MASK_DELETED_RD5).size() > 0) {
|
|
showConfirmDelete();
|
|
} else if (mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5).size() > 0) {
|
|
mBInstallerView.setOnSelectListener(null);
|
|
downloadSelectedTiles();
|
|
} else {
|
|
mBInstallerView.setOnSelectListener(null);
|
|
downloadInstalledTiles();
|
|
}
|
|
}
|
|
);
|
|
mProgressIndicator = findViewById(R.id.progressDownload);
|
|
mDownloadSummaryInfo = findViewById(R.id.textViewDownloadSummary);
|
|
mDownloadSummaryInfo.setVisibility(View.INVISIBLE);
|
|
|
|
mBaseDir = ConfigHelper.getBaseDir(this);
|
|
|
|
if (running) {
|
|
mProgressIndicator.show();
|
|
mButtonDownload.setEnabled(false);
|
|
WorkManager instance = WorkManager.getInstance(getApplicationContext());
|
|
LiveData<List<WorkInfo>> ld = instance.getWorkInfosForUniqueWorkLiveData(DownloadWorker.WORKER_NAME);
|
|
ld.observe(this, listOfWorkInfo -> {
|
|
// If there are no matching work info, do nothing
|
|
if (listOfWorkInfo == null || listOfWorkInfo.isEmpty()) {
|
|
return;
|
|
}
|
|
for (WorkInfo workInfo : listOfWorkInfo) {
|
|
startObserver(workInfo);
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
scanExistingFiles();
|
|
}
|
|
}
|
|
|
|
private String getSegmentsPlural(int count) {
|
|
Resources res = getResources();
|
|
return res.getQuantityString(R.plurals.numberOfSegments, count, count);
|
|
}
|
|
|
|
private void updateDownloadButton() {
|
|
if (mBaseDir == null) return;
|
|
final ArrayList<Integer> selectedTilesDownload = mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5);
|
|
final ArrayList<Integer> selectedTilesLastUpdate = mBInstallerView.getSelectedTiles(MASK_CURRENT_RD5);
|
|
final ArrayList<Integer> selectedTilesUpdate = mBInstallerView.getSelectedTiles(MASK_INSTALLED_RD5);
|
|
final ArrayList<Integer> selectedTilesDelete = mBInstallerView.getSelectedTiles(MASK_DELETED_RD5);
|
|
selectedTilesUpdate.removeAll(selectedTilesLastUpdate);
|
|
mSummaryInfo.setText("");
|
|
|
|
if (selectedTilesDelete.size() > 0) {
|
|
mButtonDownload.setText(getString(R.string.action_delete, getSegmentsPlural(selectedTilesDelete.size())));
|
|
mButtonDownload.setEnabled(true);
|
|
} else if (selectedTilesDownload.size() > 0) {
|
|
long tileSize = 0;
|
|
for (int tileIndex : selectedTilesDownload) {
|
|
tileSize += BInstallerSizes.getRd5Size(tileIndex);
|
|
}
|
|
mButtonDownload.setText(getString(R.string.action_download, getSegmentsPlural(selectedTilesDownload.size())));
|
|
mButtonDownload.setEnabled(true);
|
|
mSummaryInfo.setText(String.format(getString(R.string.summary_segments), Formatter.formatFileSize(this, tileSize), Formatter.formatFileSize(this, getAvailableSpace(mBaseDir.getAbsolutePath()))));
|
|
} else if (selectedTilesUpdate.size() > 0) {
|
|
mButtonDownload.setText(getString(R.string.action_update, getSegmentsPlural(selectedTilesUpdate.size())));
|
|
mButtonDownload.setEnabled(true);
|
|
} else {
|
|
mButtonDownload.setText(getString(R.string.action_select));
|
|
mButtonDownload.setEnabled(false);
|
|
}
|
|
}
|
|
|
|
private void deleteRawTracks() {
|
|
File modeDir = new File(mBaseDir, "brouter/modes");
|
|
String[] fileNames = modeDir.list();
|
|
if (fileNames == null) return;
|
|
for (String fileName : fileNames) {
|
|
if (fileName.endsWith("_rawtrack.dat")) {
|
|
File f = new File(modeDir, fileName);
|
|
f.delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void downloadAll(ArrayList<Integer> downloadList, int all) {
|
|
ArrayList<String> urlparts = new ArrayList<>();
|
|
int len = 0;
|
|
for (Integer i : downloadList) {
|
|
urlparts.add(baseNameForTile(i));
|
|
len++;
|
|
if (len > 500) break; // don't do too much work, data size 10240 Bytes only
|
|
}
|
|
|
|
downloadCanceled = false;
|
|
mProgressIndicator.show();
|
|
mButtonDownload.setEnabled(false);
|
|
|
|
Data inputData = null;
|
|
try {
|
|
inputData = new Data.Builder()
|
|
.putStringArray(DownloadWorker.KEY_INPUT_SEGMENT_NAMES, urlparts.toArray(new String[0]))
|
|
.putInt(DownloadWorker.KEY_INPUT_SEGMENT_ALL, all)
|
|
.build();
|
|
|
|
} catch (IllegalStateException e) {
|
|
Object data;
|
|
Toast.makeText(this, R.string.msg_too_much_data, Toast.LENGTH_LONG).show();
|
|
|
|
e.printStackTrace();
|
|
return;
|
|
}
|
|
|
|
Constraints constraints = new Constraints.Builder()
|
|
.setRequiresBatteryNotLow(true)
|
|
.setRequiresStorageNotLow(true)
|
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
|
.build();
|
|
|
|
OneTimeWorkRequest downloadWorkRequest =
|
|
new OneTimeWorkRequest.Builder(DownloadWorker.class)
|
|
.setInputData(inputData)
|
|
.setConstraints(constraints)
|
|
.build();
|
|
|
|
WorkManager workManager = WorkManager.getInstance(getApplicationContext());
|
|
workManager.enqueueUniqueWork(DownloadWorker.WORKER_NAME, ExistingWorkPolicy.KEEP, downloadWorkRequest);
|
|
|
|
try {
|
|
WorkInfo wi = WorkManager.getInstance(getApplicationContext()).getWorkInfoById(downloadWorkRequest.getId()).get();
|
|
if (wi != null && (wi.getState() == WorkInfo.State.ENQUEUED || wi.getState() == WorkInfo.State.BLOCKED)) {
|
|
Log.d("worker", "cancel " + wi.getState());
|
|
//WorkManager.getInstance(getApplicationContext()).cancelWorkById(downloadWorkRequest.getId());
|
|
}
|
|
} catch (ExecutionException e) {
|
|
e.printStackTrace();
|
|
} catch (InterruptedException e) {
|
|
Log.d("worker", "canceled " + e.getMessage());
|
|
//e.printStackTrace();
|
|
}
|
|
|
|
workManager
|
|
.getWorkInfoByIdLiveData(downloadWorkRequest.getId())
|
|
.observe(this, workInfo -> {
|
|
startObserver(workInfo);
|
|
});
|
|
|
|
deleteRawTracks(); // invalidate raw-tracks after data update
|
|
}
|
|
|
|
private void startObserver(WorkInfo workInfo) {
|
|
if (workInfo != null) {
|
|
if (workInfo.getState() == WorkInfo.State.ENQUEUED || workInfo.getState() == WorkInfo.State.BLOCKED) {
|
|
//WorkManager.getInstance(getApplicationContext()).cancelWorkById(downloadWorkRequest.getId());
|
|
}
|
|
|
|
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
|
|
Toast.makeText(this, R.string.msg_download_start, Toast.LENGTH_LONG).show();
|
|
mProgressIndicator.hide();
|
|
mProgressIndicator.setIndeterminate(true);
|
|
mProgressIndicator.show();
|
|
|
|
mButtonDownload.setText(getString(R.string.action_cancel));
|
|
mButtonDownload.setEnabled(true);
|
|
}
|
|
|
|
if (workInfo.getState() == WorkInfo.State.RUNNING) {
|
|
mDownloadSummaryInfo.setVisibility(View.VISIBLE);
|
|
Data progress = workInfo.getProgress();
|
|
String segmentName = progress.getString(DownloadWorker.PROGRESS_SEGMENT_NAME);
|
|
int percent = progress.getInt(DownloadWorker.PROGRESS_SEGMENT_PERCENT, 0);
|
|
if (percent > 0) {
|
|
mDownloadSummaryInfo.setText(getString(R.string.msg_download_started) + segmentName);
|
|
}
|
|
if (percent > 0) {
|
|
mProgressIndicator.setIndeterminate(false);
|
|
}
|
|
mProgressIndicator.setProgress(percent);
|
|
|
|
mButtonDownload.setText(getString(R.string.action_cancel));
|
|
mButtonDownload.setEnabled(true);
|
|
|
|
}
|
|
|
|
if (workInfo.getState().isFinished()) {
|
|
String result;
|
|
switch (workInfo.getState()) {
|
|
case FAILED:
|
|
result = getString(R.string.msg_download_failed);
|
|
break;
|
|
case CANCELLED:
|
|
result = getString(R.string.msg_download_cancel);
|
|
break;
|
|
case SUCCEEDED:
|
|
result = getString(R.string.msg_download_succeed);
|
|
break;
|
|
default:
|
|
result = "";
|
|
}
|
|
String error = null;
|
|
if (workInfo.getState() != WorkInfo.State.FAILED) {
|
|
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
|
|
} else {
|
|
error = workInfo.getOutputData().getString(DownloadWorker.KEY_OUTPUT_ERROR);
|
|
if (error != null && !error.startsWith("Version")) {
|
|
Toast.makeText(this, result + ": " + error, Toast.LENGTH_LONG).show();
|
|
}
|
|
}
|
|
|
|
if (error != null && error.startsWith("Version new app")) {
|
|
showAppUpdate();
|
|
} else if (error != null && error.startsWith("Version error")) {
|
|
showConfirmNextSteps();
|
|
} else if (error != null && error.startsWith("Version diffs")) {
|
|
showConfirmGetDiffs();
|
|
} else if (error != null) {
|
|
stopDownload();
|
|
mBInstallerView.setOnSelectListener(onSelectListener);
|
|
mBInstallerView.clearAllTilesStatus(MASK_SELECTED_RD5);
|
|
scanExistingFiles();
|
|
} else {
|
|
mBInstallerView.setOnSelectListener(onSelectListener);
|
|
mBInstallerView.clearAllTilesStatus(MASK_SELECTED_RD5);
|
|
scanExistingFiles();
|
|
}
|
|
mProgressIndicator.hide();
|
|
mDownloadSummaryInfo.setVisibility(View.INVISIBLE);
|
|
mButtonDownload.setEnabled(true);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
protected Dialog createADialog(int id) {
|
|
AlertDialog.Builder builder;
|
|
builder = new AlertDialog.Builder(this);
|
|
builder.setCancelable(false);
|
|
|
|
switch (id) {
|
|
case DIALOG_CONFIRM_DELETE_ID:
|
|
builder
|
|
.setTitle(R.string.title_delete)
|
|
.setMessage(R.string.summary_delete).setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
deleteSelectedTiles();
|
|
}
|
|
}).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
}
|
|
});
|
|
return builder.create();
|
|
|
|
case DIALOG_CONFIRM_NEXTSTEPS_ID:
|
|
builder
|
|
.setTitle(R.string.title_version)
|
|
.setMessage(R.string.summary_version)
|
|
.setPositiveButton(R.string.action_version1, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
|
|
ArrayList<Integer> allTiles = mBInstallerView.getSelectedTiles(MASK_INSTALLED_RD5);
|
|
for (Integer sel : allTiles) {
|
|
if (!selectedTiles.contains(sel)) {
|
|
mBInstallerView.toggleTileStatus(sel, 0);
|
|
new File(mBaseDir, "brouter/segments4/" + baseNameForTile(sel) + ".rd5").delete();
|
|
}
|
|
}
|
|
downloadSelectedTiles();
|
|
}
|
|
}).setNegativeButton(R.string.action_version2, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
downloadInstalledTiles();
|
|
}
|
|
}).setNeutralButton(R.string.action_version3, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
File tmplookupFile = new File(mBaseDir, "brouter/profiles2/lookups.dat.tmp");
|
|
tmplookupFile.delete();
|
|
finish();
|
|
}
|
|
});
|
|
return builder.create();
|
|
|
|
case DIALOG_CONFIRM_GETDIFFS_ID:
|
|
builder
|
|
.setTitle(R.string.title_version_diff)
|
|
.setMessage(R.string.summary_version_diff)
|
|
.setPositiveButton(R.string.action_version_diff1, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
downloadDiffVersionTiles();
|
|
}
|
|
}).setNegativeButton(R.string.action_version_diff2, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
dropDiffVersionTiles();
|
|
}
|
|
}).setNeutralButton(R.string.action_version_diff3, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
finish();
|
|
}
|
|
});
|
|
return builder.create();
|
|
case DIALOG_NEW_APP_NEEDED_ID:
|
|
builder
|
|
.setTitle(R.string.title_version)
|
|
.setMessage(R.string.summary_new_version)
|
|
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
finish();
|
|
}
|
|
});
|
|
return builder.create();
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
void showADialog(int id) {
|
|
Dialog d = createADialog(id);
|
|
if (d != null) d.show();
|
|
}
|
|
|
|
public void showConfirmDelete() {
|
|
showADialog(DIALOG_CONFIRM_DELETE_ID);
|
|
}
|
|
|
|
public void showConfirmNextSteps() {
|
|
showADialog(DIALOG_CONFIRM_NEXTSTEPS_ID);
|
|
}
|
|
|
|
private void showConfirmGetDiffs() {
|
|
showADialog(DIALOG_CONFIRM_GETDIFFS_ID);
|
|
}
|
|
|
|
private void showAppUpdate() {
|
|
showADialog(DIALOG_NEW_APP_NEEDED_ID);
|
|
}
|
|
|
|
|
|
private void scanExistingFiles() {
|
|
mBInstallerView.clearAllTilesStatus(MASK_CURRENT_RD5 | MASK_INSTALLED_RD5 | MASK_DELETED_RD5 | MASK_SELECTED_RD5);
|
|
|
|
scanExistingFiles(new File(mBaseDir, "brouter/segments4"));
|
|
|
|
File secondary = RoutingHelper.getSecondarySegmentDir(new File(mBaseDir, "brouter/segments4"));
|
|
if (secondary != null) {
|
|
scanExistingFiles(secondary);
|
|
}
|
|
}
|
|
|
|
private void scanExistingFiles(File dir) {
|
|
String[] fileNames = dir.list();
|
|
if (fileNames == null) return;
|
|
String suffix = ".rd5";
|
|
for (String fileName : fileNames) {
|
|
if (fileName.endsWith(suffix)) {
|
|
String basename = fileName.substring(0, fileName.length() - suffix.length());
|
|
int tileIndex = tileForBaseName(basename);
|
|
if (tileIndex != -1) {
|
|
mBInstallerView.setTileStatus(tileIndex, MASK_INSTALLED_RD5);
|
|
|
|
long age = System.currentTimeMillis() - new File(dir, fileName).lastModified();
|
|
if (age < 10800000) mBInstallerView.setTileStatus(tileIndex, MASK_CURRENT_RD5); // 3 hours
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void deleteSelectedTiles() {
|
|
ArrayList<Integer> selectedTiles = mBInstallerView.getSelectedTiles(MASK_DELETED_RD5);
|
|
for (int tileIndex : selectedTiles) {
|
|
new File(mBaseDir, "brouter/segments4/" + baseNameForTile(tileIndex) + ".rd5").delete();
|
|
}
|
|
scanExistingFiles();
|
|
}
|
|
|
|
private void downloadSelectedTiles() {
|
|
selectedTiles = mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5);
|
|
downloadAll(selectedTiles, DownloadWorker.VALUE_SEGMENT_PARTS);
|
|
}
|
|
|
|
private void downloadInstalledTiles() {
|
|
ArrayList<Integer> selectedTiles = mBInstallerView.getSelectedTiles(MASK_INSTALLED_RD5);
|
|
ArrayList<Integer> tmpSelectedTiles = mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5);
|
|
if (tmpSelectedTiles.size() > 0) {
|
|
selectedTiles.addAll(tmpSelectedTiles);
|
|
}
|
|
downloadAll(selectedTiles, DownloadWorker.VALUE_SEGMENT_ALL);
|
|
}
|
|
|
|
private void downloadDiffVersionTiles() {
|
|
downloadAll(new ArrayList<>(), DownloadWorker.VALUE_SEGMENT_DIFFS);
|
|
}
|
|
|
|
private void dropDiffVersionTiles() {
|
|
downloadAll(new ArrayList<>(), DownloadWorker.VALUE_SEGMENT_DROPDIFFS);
|
|
}
|
|
|
|
private boolean isDownloadRunning(Class<?> serviceClass) {
|
|
WorkManager instance = WorkManager.getInstance(getApplicationContext());
|
|
|
|
ListenableFuture<List<WorkInfo>> statuses = instance.getWorkInfosForUniqueWork(DownloadWorker.WORKER_NAME);
|
|
try {
|
|
boolean running = false;
|
|
List<WorkInfo> workInfoList = statuses.get();
|
|
for (WorkInfo workInfo : workInfoList) {
|
|
WorkInfo.State state = workInfo.getState();
|
|
running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;
|
|
}
|
|
return running;
|
|
} catch (ExecutionException e) {
|
|
e.printStackTrace();
|
|
return false;
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void stopDownload() {
|
|
WorkManager workManager = WorkManager.getInstance(getApplicationContext());
|
|
workManager.cancelAllWork();
|
|
}
|
|
|
|
private int tileForBaseName(String basename) {
|
|
String uname = basename.toUpperCase(Locale.ROOT);
|
|
int idx = uname.indexOf("_");
|
|
if (idx < 0) return -1;
|
|
String slon = uname.substring(0, idx);
|
|
String slat = uname.substring(idx + 1);
|
|
int ilon = 0;
|
|
int ilat = 0;
|
|
try {
|
|
ilon = slon.charAt(0) == 'W' ? -Integer.parseInt(slon.substring(1)) :
|
|
(slon.charAt(0) == 'E' ? Integer.parseInt(slon.substring(1)) : -1);
|
|
ilat = slat.charAt(0) == 'S' ? -Integer.parseInt(slat.substring(1)) :
|
|
(slat.charAt(0) == 'N' ? Integer.parseInt(slat.substring(1)) : -1);
|
|
} catch (NumberFormatException e) {
|
|
return -1;
|
|
}
|
|
if (ilon < -180 || ilon >= 180 || ilon % 5 != 0) return -1;
|
|
if (ilat < -90 || ilat >= 90 || ilat % 5 != 0) return -1;
|
|
return (ilon + 180) / 5 + 72 * ((ilat + 90) / 5);
|
|
}
|
|
|
|
private String baseNameForTile(int tileIndex) {
|
|
int lon = (tileIndex % 72) * 5 - 180;
|
|
int lat = (tileIndex / 72) * 5 - 90;
|
|
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
|
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
|
|
return slon + "_" + slat;
|
|
}
|
|
}
|