Require Android 5.0 (Lollipop).

This commit is contained in:
Andreas Schildbach 2021-01-10 17:15:53 +01:00
parent d988141528
commit 459db742eb
15 changed files with 33 additions and 278 deletions

View file

@ -18,13 +18,12 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="de.schildbach.oeffi"
android:versionCode="692"
android:versionName="11.4.5">
<uses-sdk
android:minSdkVersion="19"
android:minSdkVersion="21"
android:targetSdkVersion="29" />
<uses-permission android:name="android.permission.INTERNET" />
@ -64,8 +63,7 @@
android:icon="@mipmap/ic_oeffi_stations_color_48dp"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/My.Theme.Light"
tools:targetApi="24">
android:theme="@style/My.Theme.Light">
<provider
android:name="androidx.core.content.FileProvider"

View file

@ -1,13 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<de.schildbach.oeffi.MyActionBar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:elevation="@dimen/elevation_action_bar"
tools:targetApi="21">
android:elevation="@dimen/elevation_action_bar">
<ImageButton
android:id="@+id/action_bar_menu_button"

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
@ -11,8 +10,7 @@
android:id="@+id/navigation_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="@dimen/elevation_content"
tools:targetApi="21">
android:elevation="@dimen/elevation_content">
<LinearLayout
android:id="@+id/directions_content_layout"
@ -90,8 +88,7 @@
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="@android:color/white"
android:elevation="@dimen/elevation_panel"
tools:targetApi="21">
android:elevation="@dimen/elevation_panel">
<include layout="@layout/directions_form_include" />
</ScrollView>
@ -105,8 +102,7 @@
android:id="@+id/directions_map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="@dimen/elevation_map"
tools:targetApi="21">
android:elevation="@dimen/elevation_map">
<de.schildbach.oeffi.OeffiMapView
android:id="@+id/directions_map"

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/stations_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -13,8 +12,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:elevation="@dimen/elevation_content"
tools:targetApi="21">
android:elevation="@dimen/elevation_content">
<include layout="@layout/action_bar" />
@ -122,8 +120,7 @@
android:id="@+id/directions_trip_details_map_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="@dimen/elevation_map"
tools:targetApi="21">
android:elevation="@dimen/elevation_map">
<de.schildbach.oeffi.OeffiMapView
android:id="@+id/directions_trip_details_map"

View file

@ -1,14 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/stations_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:elevation="@dimen/elevation_content"
android:orientation="horizontal"
tools:targetApi="21">
android:orientation="horizontal">
<LinearLayout
android:id="@+id/network_picker_list_frame"

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
@ -11,8 +10,7 @@
android:id="@+id/navigation_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="@dimen/elevation_content"
tools:targetApi="21">
android:elevation="@dimen/elevation_content">
<LinearLayout
android:layout_width="match_parent"
@ -404,8 +402,7 @@
android:id="@+id/stations_map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="@dimen/elevation_map"
tools:targetApi="21">
android:elevation="@dimen/elevation_map">
<de.schildbach.oeffi.OeffiMapView
android:id="@+id/stations_map"

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
@ -12,8 +11,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="@dimen/elevation_content"
android:orientation="vertical"
tools:targetApi="21">
android:orientation="vertical">
<include layout="@layout/action_bar" />
@ -80,8 +78,7 @@
android:id="@+id/stations_station_details_map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="@dimen/elevation_map"
tools:targetApi="21">
android:elevation="@dimen/elevation_map">
<de.schildbach.oeffi.OeffiMapView
android:id="@+id/stations_station_details_map"

View file

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<style name="My.Theme.Light" parent="@android:style/Theme.Material.Light.NoActionBar">
<item name="android:windowBackground">@android:color/white</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:textViewStyle">@style/My.Widget.TextView</item>
<item name="android:autoCompleteTextViewStyle">@style/My.Widget.AutoCompleteTextView</item>
<item name="android:dropDownListViewStyle">@style/My.Widget.ListView.DropDown</item>
<item name="android:buttonStyle">@style/My.Widget.Button</item>
<item name="android:imageButtonStyle">@style/My.Widget.ImageButton</item>
<item name="android:checkboxStyle">@style/My.Widget.CompoundButton.CheckBox</item>
<item name="android:popupMenuStyle">@style/My.Widget.PopupMenu</item>
</style>
<style name="My.Theme.Dark" parent="@android:style/Theme.Material.NoActionBar">
<item name="android:windowBackground">@android:color/black</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:imageButtonStyle">@style/My.Widget.ImageButton</item>
</style>
<style name="My.Theme.Fullscreen" parent="@android:style/Theme.Material.Light.NoActionBar.Fullscreen">
<item name="android:windowBackground">@android:color/black</item>
<item name="android:textViewStyle">@style/My.Widget.TextView</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="27">shortEdges</item>
</style>
<style name="My.Theme.Preference" parent="@android:style/Theme.Material.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/My.Widget.ActionBar</item>
</style>
<style name="My.Widget.AutoCompleteTextView" parent="@android:style/Widget.Material.Light.AutoCompleteTextView">
<item name="android:textColor">@color/fg_significant</item>
<item name="android:background">@null</item>
<item name="android:popupBackground">@android:color/white</item>
<item name="android:dropDownVerticalOffset">0px</item>
</style>
<style name="My.Widget.Button" parent="@android:style/Widget.Material.Light.Button">
<item name="android:background">?android:attr/selectableItemBackground</item>
<item name="android:textColor">@color/fg_significant</item>
<item name="android:textSize">@dimen/font_size_normal</item>
<item name="android:textAllCaps">false</item>
</style>
<style name="My.Widget.Button.Border" parent="@android:style/Widget.Material.Light.Button">
<item name="android:textColor">@color/fg_significant</item>
<item name="android:textSize">@dimen/font_size_normal</item>
</style>
<style name="My.Widget.CompoundButton.CheckBox" parent="@android:style/Widget.Material.CompoundButton.CheckBox">
<item name="android:textSize">@dimen/font_size_normal</item>
</style>
<style name="My.Widget.ListView.DropDown" parent="@android:style/Widget.Material.ListView.DropDown">
<item name="android:divider">@null</item>
</style>
<style name="My.Widget.PopupMenu" parent="@android:style/Widget.Material.Light.PopupMenu" />
<style name="My.Widget.ActionBar" parent="@android:style/Widget.Material.ActionBar.Solid">
<item name="android:background">@color/bg_action_bar</item>
<item name="android:titleTextStyle">@style/My.TextAppearance.Widget.ActionBar.Title</item>
<item name="android:displayOptions">homeAsUp|showTitle</item>
</style>
<style name="My.TextAppearance.Widget.ActionBar.Title" parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
<item name="android:textColor">@android:color/white</item>
<item name="android:textStyle">bold</item>
</style>
</resources>

View file

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<style name="My.Theme.Light" parent="@android:style/Theme.Holo.Light.NoActionBar">
<style name="My.Theme.Light" parent="@android:style/Theme.Material.Light.NoActionBar">
<item name="android:windowBackground">@android:color/white</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:textViewStyle">@style/My.Widget.TextView</item>
@ -14,18 +15,19 @@
<item name="android:popupMenuStyle">@style/My.Widget.PopupMenu</item>
</style>
<style name="My.Theme.Dark" parent="@android:style/Theme.Holo.NoActionBar">
<style name="My.Theme.Dark" parent="@android:style/Theme.Material.NoActionBar">
<item name="android:windowBackground">@android:color/black</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:imageButtonStyle">@style/My.Widget.ImageButton</item>
</style>
<style name="My.Theme.Fullscreen" parent="@android:style/Theme.Holo.Light.NoActionBar.Fullscreen">
<style name="My.Theme.Fullscreen" parent="@android:style/Theme.Material.Light.NoActionBar.Fullscreen">
<item name="android:windowBackground">@android:color/black</item>
<item name="android:textViewStyle">@style/My.Widget.TextView</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="27">shortEdges</item>
</style>
<style name="My.Theme.Preference" parent="@android:style/Theme.Holo.Light.DarkActionBar">
<style name="My.Theme.Preference" parent="@android:style/Theme.Material.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/My.Widget.ActionBar</item>
</style>
@ -41,20 +43,21 @@
<item name="android:textSize">@dimen/font_size_normal</item>
</style>
<style name="My.Widget.AutoCompleteTextView" parent="@android:style/Widget.Holo.Light.AutoCompleteTextView">
<style name="My.Widget.AutoCompleteTextView" parent="@android:style/Widget.Material.Light.AutoCompleteTextView">
<item name="android:textColor">@color/fg_significant</item>
<item name="android:background">@null</item>
<item name="android:popupBackground">@android:color/white</item>
<item name="android:dropDownVerticalOffset">0px</item>
</style>
<style name="My.Widget.Button" parent="@android:style/Widget.Holo.Light.Button">
<style name="My.Widget.Button" parent="@android:style/Widget.Material.Light.Button">
<item name="android:background">?android:attr/selectableItemBackground</item>
<item name="android:textColor">@color/fg_significant</item>
<item name="android:textSize">@dimen/font_size_normal</item>
<item name="android:textAllCaps">false</item>
</style>
<style name="My.Widget.Button.Border" parent="@android:style/Widget.Holo.Light.Button">
<style name="My.Widget.Button.Border" parent="@android:style/Widget.Material.Light.Button">
<item name="android:textColor">@color/fg_significant</item>
<item name="android:textSize">@dimen/font_size_normal</item>
</style>
@ -69,23 +72,23 @@
<item name="android:src">@drawable/ic_more_vert_grey600_24dp</item>
</style>
<style name="My.Widget.CompoundButton.CheckBox" parent="@android:style/Widget.Holo.CompoundButton.CheckBox">
<style name="My.Widget.CompoundButton.CheckBox" parent="@android:style/Widget.Material.CompoundButton.CheckBox">
<item name="android:textSize">@dimen/font_size_normal</item>
</style>
<style name="My.Widget.ListView.DropDown" parent="@android:style/Widget.Holo.ListView.DropDown">
<style name="My.Widget.ListView.DropDown" parent="@android:style/Widget.Material.ListView.DropDown">
<item name="android:divider">@null</item>
</style>
<style name="My.Widget.PopupMenu" parent="@android:style/Widget.Holo.Light.PopupMenu" />
<style name="My.Widget.PopupMenu" parent="@android:style/Widget.Material.Light.PopupMenu" />
<style name="My.Widget.ActionBar" parent="@android:style/Widget.Holo.ActionBar.Solid">
<style name="My.Widget.ActionBar" parent="@android:style/Widget.Material.ActionBar.Solid">
<item name="android:background">@color/bg_action_bar</item>
<item name="android:titleTextStyle">@style/My.TextAppearance.Widget.ActionBar.Title</item>
<item name="android:displayOptions">homeAsUp|showTitle</item>
</style>
<style name="My.TextAppearance.Widget.ActionBar.Title" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
<style name="My.TextAppearance.Widget.ActionBar.Title" parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
<item name="android:textColor">@android:color/white</item>
<item name="android:textStyle">bold</item>
</style>

View file

@ -47,7 +47,6 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FilenameFilter;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
public class Application extends android.app.Application {
@ -86,13 +85,6 @@ public class Application extends android.app.Application {
});
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
builder.addNetworkInterceptor(interceptor);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
log.info("manually enabling TLS 1.2 on API level {}", Build.VERSION.SDK_INT);
if (safetyNetInsertProvider()) {
final Tls12SocketFactory socketFactory = new Tls12SocketFactory();
builder.sslSocketFactory(socketFactory, socketFactory.getTrustManager());
}
}
okHttpClient = builder.build();
initMaps();
@ -127,23 +119,6 @@ public class Application extends android.app.Application {
initNotificationManager();
}
private boolean safetyNetInsertProvider() {
// This piece of code uses SafetyNet (Google Play Services) to insert a recent version of Conscrypt, if
// available. We use reflection to avoid the proprietary Google Play Services client library.
try {
final Stopwatch watch = Stopwatch.createStarted();
final Context remoteContext = createPackageContext("com.google.android.gms", 3);
final Method insertProvider = remoteContext.getClassLoader().loadClass("com.google.android.gms.common" +
".security.ProviderInstallerImpl").getMethod("insertProvider", new Class[] { Context.class });
insertProvider.invoke(null, new Object[] { remoteContext });
log.info("insertProvider successful, took {}", watch.stop());
return true;
} catch (final Exception x) {
log.warn("insertProvider failed", x);
return false;
}
}
private void initLogging() {
final File logDir = new File(getFilesDir(), "log");
final File logFile = new File(logDir, "oeffi.log");

View file

@ -17,8 +17,6 @@
package de.schildbach.oeffi;
import android.app.AlertDialog;
import android.os.Build;
import android.text.format.DateUtils;
import okhttp3.HttpUrl;
@ -74,6 +72,5 @@ public class Constants {
public static final String DESTINATION_ARROW_INVISIBLE_PREFIX = " ";
@SuppressWarnings("deprecation")
public static final int ALERT_DIALOG_THEME = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
? AlertDialog.THEME_DEVICE_DEFAULT_LIGHT : android.R.style.Theme_DeviceDefault_Light_Dialog;
public static final int ALERT_DIALOG_THEME = android.R.style.Theme_DeviceDefault_Light_Dialog;
}

View file

@ -115,8 +115,7 @@ public abstract class OeffiActivity extends Activity {
protected final void setPrimaryColor(final int colorResId) {
final int color = getResources().getColor(colorResId);
getMyActionBar().setBackgroundColor(color);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
setTaskDescription(new TaskDescription(null, null, color));
setTaskDescription(new TaskDescription(null, null, color));
}
protected void updateDisclaimerSource(final TextView disclaimerSourceView, final String network,

View file

@ -1,118 +0,0 @@
/*
* Copyright the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.schildbach.oeffi;
import androidx.annotation.Nullable;
import okhttp3.TlsVersion;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
public final class Tls12SocketFactory extends SSLSocketFactory {
private final SSLSocketFactory delegate;
private final TrustManager[] trustManagers;
public Tls12SocketFactory() {
try {
final TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
trustManagers = trustManagerFactory.getTrustManagers();
final SSLContext context = SSLContext.getInstance(TlsVersion.TLS_1_2.javaName());
context.init(null, trustManagers, null);
delegate = context.getSocketFactory();
} catch (final NoSuchAlgorithmException | KeyManagementException | KeyStoreException x) {
throw new RuntimeException(x);
}
}
@Nullable
public X509TrustManager getTrustManager() {
for (final TrustManager tm : trustManagers)
if (tm instanceof X509TrustManager)
return (X509TrustManager) tm;
return null;
}
@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return patchForTls12(delegate.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return patchForTls12(delegate.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return patchForTls12(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException,
UnknownHostException {
return patchForTls12(delegate.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return patchForTls12(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return patchForTls12(delegate.createSocket(address, port, localAddress, localPort));
}
private Socket patchForTls12(final Socket socket) {
if (socket != null && (socket instanceof SSLSocket)) {
final SSLSocket sslSocket = (SSLSocket) socket;
final Set<String> protocols = new TreeSet<>();
protocols.addAll(Arrays.asList(sslSocket.getEnabledProtocols()));
protocols.add(TlsVersion.TLS_1_2.javaName());
sslSocket.setEnabledProtocols(protocols.toArray(new String[0]));
}
return socket;
}
}

View file

@ -560,8 +560,7 @@ public class NetworkPickerActivity extends Activity implements ActivityCompat.On
protected final void setPrimaryColor(final int colorResId) {
final int color = getResources().getColor(colorResId);
actionBar.setBackgroundColor(color);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
setTaskDescription(new TaskDescription(null, null, color));
setTaskDescription(new TaskDescription(null, null, color));
}
@TargetApi(24)

View file

@ -17,7 +17,6 @@
package de.schildbach.oeffi.network;
import android.os.Build;
import com.google.common.base.Charsets;
import de.schildbach.pte.AbstractNetworkProvider;
import de.schildbach.pte.AvvAachenProvider;
@ -97,8 +96,6 @@ public final class NetworkProviderFactory {
final AbstractNetworkProvider networkProvider = forId(networkId);
networkProvider.setUserAgent(USER_AGENT);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
networkProvider.setTrustAllCertificates(true);
providerCache.put(networkId, networkProvider);
return networkProvider;
}
@ -170,11 +167,7 @@ public final class NetworkProviderFactory {
else if (networkId.equals(NetworkId.VVV))
return new VvvProvider();
else if (networkId.equals(NetworkId.OEBB))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return new OebbProvider("{\"type\":\"AID\",\"aid\":\"OWDL4fE4ixNiPBBm\"}");
else
return new OebbProvider(HttpUrl.parse("http://fahrplan.oebb.at/bin/"), "{\"type\":\"AID\"," +
"\"aid\":\"OWDL4fE4ixNiPBBm\"}");
return new OebbProvider("{\"type\":\"AID\",\"aid\":\"OWDL4fE4ixNiPBBm\"}");
else if (networkId.equals(NetworkId.WIEN))
return new WienProvider();
else if (networkId.equals(NetworkId.LINZ))