Merge pull request #364 from zod/essbee-profile-intent
Add intent receiver for profiles @zod and @EssBee59 Many thanks for your work.
This commit is contained in:
commit
8088b13d63
6 changed files with 337 additions and 52 deletions
|
@ -16,7 +16,8 @@
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:preserveLegacyExternalStorage="true">
|
android:preserveLegacyExternalStorage="true">
|
||||||
<activity android:name=".BRouterActivity"
|
<activity
|
||||||
|
android:name=".BRouterActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:screenOrientation="unspecified"
|
android:screenOrientation="unspecified"
|
||||||
|
@ -26,23 +27,76 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".BInstallerActivity"
|
<activity
|
||||||
|
android:name=".BInstallerActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:screenOrientation="landscape"
|
android:screenOrientation="landscape"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"></activity>
|
||||||
|
<activity
|
||||||
|
android:name=".BImportActivity"
|
||||||
|
android:label="Import Profile"
|
||||||
|
android:exported="true"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar">
|
||||||
|
<!-- some apps (bluemail) do not recognize the .brf file extention, startactivity+intent is done for attachement with text/plain -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:scheme="content" />
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- general intent to register .brf files -->
|
||||||
|
<intent-filter
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:priority="50">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:scheme="content" />
|
||||||
|
<data android:host="*" />
|
||||||
|
<data android:pathPattern=".*\\.brf" />
|
||||||
|
<data android:pathPattern=".*\\..*\\.brf" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\.brf" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\.brf" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.brf" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:priority="50">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:scheme="content" />
|
||||||
|
<data android:host="*" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
<data android:pathPattern=".*\\.brf" />
|
||||||
|
<data android:pathPattern=".*\\..*\\.brf" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\.brf" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\.brf" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.brf" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:name=".BRouterService"
|
android:name=".BRouterService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:process=":brouter_service" />
|
android:process=":brouter_service" />
|
||||||
<service android:name="btools.routingapp.DownloadService"
|
<service
|
||||||
|
android:name="btools.routingapp.DownloadService"
|
||||||
android:label="Download Service"
|
android:label="Download Service"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:enabled="true"
|
android:enabled="true" />
|
||||||
/>
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
package btools.routingapp;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.OpenableColumns;
|
||||||
|
import android.text.format.Formatter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
public class BImportActivity extends Activity {
|
||||||
|
// profile size is generally < 30 kb, so set max size to 100 kb
|
||||||
|
private static final int MAX_PROFILE_SIZE = 100000;
|
||||||
|
private EditText mTextFilename;
|
||||||
|
private Button mButtonImport;
|
||||||
|
private String mProfileData;
|
||||||
|
private EditText mTextProfile;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.import_intent);
|
||||||
|
mTextFilename = findViewById(R.id.editTextFilename);
|
||||||
|
mButtonImport = findViewById(R.id.buttonImport);
|
||||||
|
mButtonImport.setEnabled(false);
|
||||||
|
mButtonImport.setOnClickListener(view -> importProfile());
|
||||||
|
mTextProfile = findViewById(R.id.editTextProfile);
|
||||||
|
|
||||||
|
Intent intent = getIntent();
|
||||||
|
String action = intent.getAction();
|
||||||
|
if (Intent.ACTION_VIEW.equals(action)) {
|
||||||
|
parseIntent(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBuiltinProfile(String filename) {
|
||||||
|
String[] builtinProfiles = new ServerConfig(this).getProfiles();
|
||||||
|
for (String builtinProfile : builtinProfiles) {
|
||||||
|
if (filename.equals(builtinProfile)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInvalidProfileFilename(String filename) {
|
||||||
|
return !filename.endsWith(".brf");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseIntent(Intent intent) {
|
||||||
|
if (intent.getData() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder resultMessage = new StringBuilder();
|
||||||
|
Uri dataUri = intent.getData();
|
||||||
|
|
||||||
|
// by some apps (bluemail) the file name must be "extracted" from the URI, as example with the following code
|
||||||
|
// see https://stackoverflow.com/questions/14364091/retrieve-file-path-from-caught-downloadmanager-intent
|
||||||
|
// URI example ==> dat=content://me.bluemail.mail.attachmentprovider/a2939069-76b5-44e4-8cbd-94485d0fd4ff/cc32b61d-97a6-4871-b67f-945d1d1d43c8/VIEW
|
||||||
|
String filename = null;
|
||||||
|
long filesize = 0L;
|
||||||
|
try (Cursor cursor = this.getContentResolver().query(intent.getData(), new String[]{
|
||||||
|
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}, null, null, null)) {
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
||||||
|
filesize = cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// is the file extention ".brf" in the file name
|
||||||
|
if (filename == null || isInvalidProfileFilename(filename)) {
|
||||||
|
resultMessage.append("ERROR: File extention must be \".brf\"\n");
|
||||||
|
displayMessage(resultMessage.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filesize > MAX_PROFILE_SIZE) {
|
||||||
|
String errorMessage = String.format("ERROR: File size (%s) exceeds limit (%s)\n",
|
||||||
|
Formatter.formatFileSize(this, filesize),
|
||||||
|
Formatter.formatFileSize(this, MAX_PROFILE_SIZE));
|
||||||
|
displayMessage(errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (
|
||||||
|
InputStream inputStream = getContentResolver().openInputStream(dataUri);
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String line = br.readLine();
|
||||||
|
|
||||||
|
while (line != null) {
|
||||||
|
sb.append(line);
|
||||||
|
sb.append(System.getProperty("line.separator"));
|
||||||
|
line = br.readLine();
|
||||||
|
}
|
||||||
|
mProfileData = sb.toString();
|
||||||
|
} catch (IOException e) {
|
||||||
|
resultMessage.append(String.format("ERROR: failed to load profile content (%s)", e.getMessage()));
|
||||||
|
displayMessage(resultMessage.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mProfileData.contains("---context:global") || (!mProfileData.contains("---context:way"))) {
|
||||||
|
resultMessage.append("ERROR: this file is not a valid brouter-profile\n");
|
||||||
|
displayMessage(resultMessage.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextFilename.setText(filename);
|
||||||
|
mTextProfile.setText(mProfileData);
|
||||||
|
mButtonImport.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayMessage(String message) {
|
||||||
|
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean importProfile() {
|
||||||
|
String filename = mTextFilename.getText().toString();
|
||||||
|
if (isInvalidProfileFilename(filename)) {
|
||||||
|
displayMessage("ERROR: File extention must be \".brf\"\n");
|
||||||
|
return false;
|
||||||
|
} else if (isBuiltinProfile(filename)) {
|
||||||
|
displayMessage("ERROR: Built-in profile exists\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeProfile(filename, mProfileData);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeProfile(String filename, String profileData) {
|
||||||
|
File baseDir = ConfigHelper.getBaseDir(this);
|
||||||
|
|
||||||
|
try {
|
||||||
|
File file = new File(baseDir, "brouter/profiles2/" + filename);
|
||||||
|
FileOutputStream stream = new FileOutputStream(file);
|
||||||
|
stream.write(profileData.getBytes());
|
||||||
|
stream.close();
|
||||||
|
displayMessage("Profile successfully imported");
|
||||||
|
} catch (IOException e) {
|
||||||
|
displayMessage(String.format("Profile import failed: %s", e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,14 +11,11 @@ import android.os.HandlerThread;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.StatFs;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -35,11 +32,7 @@ public class DownloadService extends Service implements ProgressListener {
|
||||||
|
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
String segmenturl = "https://brouter.de/brouter/segments4/";
|
private ServerConfig mServerConfig;
|
||||||
String lookupurl = "https://brouter.de/brouter/profile2/";
|
|
||||||
String profilesurl = "https://brouter.de/brouter/profile2/";
|
|
||||||
String checkLookup = "lookups.dat";
|
|
||||||
String checkProfiles = "";
|
|
||||||
|
|
||||||
private NotificationHelper mNotificationHelper;
|
private NotificationHelper mNotificationHelper;
|
||||||
private List<String> mUrlList;
|
private List<String> mUrlList;
|
||||||
|
@ -78,6 +71,7 @@ public class DownloadService extends Service implements ProgressListener {
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
if (DEBUG) Log.d("SERVICE", "onCreate");
|
if (DEBUG) Log.d("SERVICE", "onCreate");
|
||||||
serviceState = true;
|
serviceState = true;
|
||||||
|
mServerConfig = new ServerConfig(getApplicationContext());
|
||||||
|
|
||||||
HandlerThread thread = new HandlerThread("ServiceStartArguments", 1);
|
HandlerThread thread = new HandlerThread("ServiceStartArguments", 1);
|
||||||
thread.start();
|
thread.start();
|
||||||
|
@ -109,38 +103,6 @@ public class DownloadService extends Service implements ProgressListener {
|
||||||
List<String> urlparts = extra.getStringArrayList("urlparts");
|
List<String> urlparts = extra.getStringArrayList("urlparts");
|
||||||
mUrlList = urlparts;
|
mUrlList = urlparts;
|
||||||
baseDir = dir;
|
baseDir = dir;
|
||||||
|
|
||||||
File configFile = new File (dir, "segments4/serverconfig.txt");
|
|
||||||
if ( configFile.exists() ) {
|
|
||||||
try {
|
|
||||||
BufferedReader br = new BufferedReader( new FileReader( configFile ) );
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
String line = br.readLine();
|
|
||||||
if ( line == null ) break;
|
|
||||||
if ( line.trim().startsWith( "segment_url=" ) ) {
|
|
||||||
segmenturl = line.substring(12);
|
|
||||||
}
|
|
||||||
else if ( line.trim().startsWith( "lookup_url=" ) ) {
|
|
||||||
lookupurl = line.substring(11);
|
|
||||||
}
|
|
||||||
else if ( line.trim().startsWith( "profiles_url=" ) ) {
|
|
||||||
profilesurl = line.substring(13);
|
|
||||||
}
|
|
||||||
else if ( line.trim().startsWith( "check_lookup=" ) ) {
|
|
||||||
checkLookup = line.substring(13);
|
|
||||||
}
|
|
||||||
else if ( line.trim().startsWith( "check_profiles=" ) ) {
|
|
||||||
checkProfiles = line.substring(15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
br.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mNotificationHelper.startNotification(this);
|
mNotificationHelper.startNotification(this);
|
||||||
|
@ -185,7 +147,7 @@ public class DownloadService extends Service implements ProgressListener {
|
||||||
int count = 1;
|
int count = 1;
|
||||||
int size = mUrlList.size();
|
int size = mUrlList.size();
|
||||||
for (String part: mUrlList) {
|
for (String part: mUrlList) {
|
||||||
String url = segmenturl + part + ".rd5";
|
String url = mServerConfig.getSegmentUrl() + part + ".rd5";
|
||||||
if (DEBUG) Log.d("BR", "downlaod " + url);
|
if (DEBUG) Log.d("BR", "downlaod " + url);
|
||||||
|
|
||||||
result = download(count, size, url);
|
result = download(count, size, url);
|
||||||
|
@ -386,7 +348,7 @@ public class DownloadService extends Service implements ProgressListener {
|
||||||
|
|
||||||
private String checkScripts() {
|
private String checkScripts() {
|
||||||
|
|
||||||
String[] sa = checkLookup.split(",");
|
String[] sa = mServerConfig.getLookups();
|
||||||
for (String f: sa) {
|
for (String f: sa) {
|
||||||
if (f.length()>0) {
|
if (f.length()>0) {
|
||||||
File file = new File(baseDir + "profiles2", f);
|
File file = new File(baseDir + "profiles2", f);
|
||||||
|
@ -394,7 +356,7 @@ public class DownloadService extends Service implements ProgressListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sa = checkProfiles.split(",");
|
sa = mServerConfig.getProfiles();
|
||||||
for (String f : sa) {
|
for (String f : sa) {
|
||||||
if (f.length()>0) {
|
if (f.length()>0) {
|
||||||
File file = new File(baseDir + "profiles2", f);
|
File file = new File(baseDir + "profiles2", f);
|
||||||
|
@ -410,12 +372,12 @@ public class DownloadService extends Service implements ProgressListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String checkOrDownloadLookup(String fileName, File f) {
|
private String checkOrDownloadLookup(String fileName, File f) {
|
||||||
String url = lookupurl + fileName;
|
String url = mServerConfig.getLookupUrl() + fileName;
|
||||||
return downloadScript(url, f);
|
return downloadScript(url, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String checkOrDownloadScript(String fileName, File f) {
|
private String checkOrDownloadScript(String fileName, File f) {
|
||||||
String url = profilesurl + fileName;
|
String url = mServerConfig.getProfilesUrl() + fileName;
|
||||||
return downloadScript(url, f);
|
return downloadScript(url, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package btools.routingapp;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ServerConfig {
|
||||||
|
private String mSegmentUrl = "https://brouter.de/brouter/segments4/";
|
||||||
|
private String mLookupsUrl = "https://brouter.de/brouter/profiles2/";
|
||||||
|
private String mProfilesUrl = "https://brouter.de/brouter/profiles2/";
|
||||||
|
|
||||||
|
private String[] mLookups = new String[]{"lookups.dat"};
|
||||||
|
private String[] mProfiles = new String[0];
|
||||||
|
|
||||||
|
public ServerConfig(Context ctx) {
|
||||||
|
File configFile = new File(ConfigHelper.getBaseDir(ctx), "/brouter/segments4/serverconfig.txt");
|
||||||
|
if (configFile.exists()) {
|
||||||
|
try {
|
||||||
|
BufferedReader br = new BufferedReader(new FileReader(configFile));
|
||||||
|
for (; ; ) {
|
||||||
|
String line = br.readLine();
|
||||||
|
if (line == null) break;
|
||||||
|
if (line.trim().startsWith("segment_url=")) {
|
||||||
|
mSegmentUrl = line.substring(12);
|
||||||
|
} else if (line.trim().startsWith("lookup_url=")) {
|
||||||
|
mLookupsUrl = line.substring(11);
|
||||||
|
} else if (line.trim().startsWith("profiles_url=")) {
|
||||||
|
mProfilesUrl = line.substring(13);
|
||||||
|
} else if (line.trim().startsWith("check_lookup=")) {
|
||||||
|
mLookups = line.substring(13).split(",");
|
||||||
|
} else if (line.trim().startsWith("check_profiles=")) {
|
||||||
|
mProfiles = line.substring(15).split(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSegmentUrl() {
|
||||||
|
return mSegmentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLookupUrl() {
|
||||||
|
return mLookupsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProfilesUrl() {
|
||||||
|
return mProfilesUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getLookups() {
|
||||||
|
return mLookups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getProfiles() {
|
||||||
|
return mProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
brouter-routing-app/src/main/res/layout/import_intent.xml
Normal file
43
brouter-routing-app/src/main/res/layout/import_intent.xml
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
tools:context=".BImportActivity">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/buttonImport"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:text="@string/import_profile"
|
||||||
|
android:layout_alignParentEnd="true" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/editTextFilename"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:ems="10"
|
||||||
|
android:hint="@string/profile_filename_example"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textUri"
|
||||||
|
android:minHeight="48dp" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/editTextProfile"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@id/buttonImport"
|
||||||
|
android:layout_below="@id/editTextFilename"
|
||||||
|
android:ems="8"
|
||||||
|
android:enabled="false"
|
||||||
|
android:gravity="start|top"
|
||||||
|
android:inputType="none"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:importantForAutofill="no" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
|
@ -16,4 +16,6 @@
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">BRouter</string>
|
<string name="app_name">BRouter</string>
|
||||||
|
<string name="import_profile">Import Profile</string>
|
||||||
|
<string name="profile_filename_example">filename.brf</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue