diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ce0ab5c6..bac0855e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -90,6 +90,7 @@
+
diff --git a/app/src/main/assets/licenses/Android AppCompat Library V7 b/app/src/main/assets/licenses/Android AppCompat Library V7
new file mode 100644
index 00000000..b87d6ec7
--- /dev/null
+++ b/app/src/main/assets/licenses/Android AppCompat Library V7
@@ -0,0 +1,13 @@
+Copyright (C) 2019 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/app/src/main/assets/licenses/Android Lifecycle Extensions b/app/src/main/assets/licenses/Android Lifecycle Extensions
new file mode 100644
index 00000000..b87d6ec7
--- /dev/null
+++ b/app/src/main/assets/licenses/Android Lifecycle Extensions
@@ -0,0 +1,13 @@
+Copyright (C) 2019 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/app/src/main/assets/licenses/Android Support Preference V7 b/app/src/main/assets/licenses/Android Support Preference V7
new file mode 100644
index 00000000..b87d6ec7
--- /dev/null
+++ b/app/src/main/assets/licenses/Android Support Preference V7
@@ -0,0 +1,13 @@
+Copyright (C) 2019 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/app/src/main/assets/licenses/Glide b/app/src/main/assets/licenses/Glide
new file mode 100644
index 00000000..441c3743
--- /dev/null
+++ b/app/src/main/assets/licenses/Glide
@@ -0,0 +1,94 @@
+License for everything not in third_party and not otherwise marked:
+
+Copyright 2014 Google, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are
+permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of
+ conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ of conditions and the following disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those of the
+authors and should not be interpreted as representing official policies, either expressed
+or implied, of Google, Inc.
+---------------------------------------------------------------------------------------------
+License for third_party/disklrucache:
+
+Copyright 2012 Jake Wharton
+Copyright 2011 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+---------------------------------------------------------------------------------------------
+License for third_party/gif_decoder:
+
+Copyright (c) 2013 Xcellent Creations, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+---------------------------------------------------------------------------------------------
+License for third_party/gif_encoder/AnimatedGifEncoder.java and
+third_party/gif_encoder/LZWEncoder.java:
+
+No copyright asserted on the source code of this class. May be used for any
+purpose, however, refer to the Unisys LZW patent for restrictions on use of
+the associated LZWEncoder class. Please forward any corrections to
+kweiner@fmsware.com.
+
+-----------------------------------------------------------------------------
+License for third_party/gif_encoder/NeuQuant.java
+
+Copyright (c) 1994 Anthony Dekker
+
+NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See
+"Kohonen neural networks for optimal colour quantization" in "Network:
+Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of
+the algorithm.
+
+Any party obtaining a copy of these files from the author, directly or
+indirectly, is granted, free of charge, a full and unrestricted irrevocable,
+world-wide, paid up, royalty-free, nonexclusive right and license to deal in
+this software and documentation files (the "Software"), including without
+limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons who
+receive copies from any such party to do so, with the only requirement being
+that this copyright notice remain intact.
\ No newline at end of file
diff --git a/app/src/main/assets/licenses/Material Components for Android b/app/src/main/assets/licenses/Material Components for Android
new file mode 100644
index 00000000..b87d6ec7
--- /dev/null
+++ b/app/src/main/assets/licenses/Material Components for Android
@@ -0,0 +1,13 @@
+Copyright (C) 2019 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/app/src/main/assets/licenses/PseudoApkSigner b/app/src/main/assets/licenses/PseudoApkSigner
new file mode 100644
index 00000000..1a0c97c6
--- /dev/null
+++ b/app/src/main/assets/licenses/PseudoApkSigner
@@ -0,0 +1,13 @@
+Copyright (C) 2019 Aefyr
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/app/src/main/assets/licenses/Shizuku b/app/src/main/assets/licenses/Shizuku
new file mode 100644
index 00000000..e5e78495
--- /dev/null
+++ b/app/src/main/assets/licenses/Shizuku
@@ -0,0 +1,13 @@
+Copyright (C) 2019 Rikka
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/app/src/main/assets/licenses/android-filepicker b/app/src/main/assets/licenses/android-filepicker
new file mode 100644
index 00000000..9d5b7e83
--- /dev/null
+++ b/app/src/main/assets/licenses/android-filepicker
@@ -0,0 +1,13 @@
+Copyright (C) 2016 Angad Singh
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/app/src/main/java/com/aefyr/sai/adapters/LicensesAdapter.java b/app/src/main/java/com/aefyr/sai/adapters/LicensesAdapter.java
new file mode 100644
index 00000000..0359c8f8
--- /dev/null
+++ b/app/src/main/java/com/aefyr/sai/adapters/LicensesAdapter.java
@@ -0,0 +1,66 @@
+package com.aefyr.sai.adapters;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.aefyr.sai.R;
+import com.aefyr.sai.model.licenses.License;
+
+import java.util.List;
+
+public class LicensesAdapter extends RecyclerView.Adapter {
+
+ private LayoutInflater mInflater;
+
+ private List mLicenses;
+
+ public LicensesAdapter(Context c) {
+ mInflater = LayoutInflater.from(c);
+ }
+
+ public void setLicenses(List licenses) {
+ mLicenses = licenses;
+ notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new ViewHolder(mInflater.inflate(R.layout.item_license, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ holder.bind(mLicenses.get(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return mLicenses == null ? 0 : mLicenses.size();
+ }
+
+ class ViewHolder extends RecyclerView.ViewHolder {
+
+ private TextView mSubject;
+ private TextView mText;
+
+ private ViewHolder(@NonNull View itemView) {
+ super(itemView);
+
+ mSubject = itemView.findViewById(R.id.tv_subject);
+ mText = itemView.findViewById(R.id.tv_text);
+ }
+
+ private void bind(License license) {
+ mSubject.setText(license.subject);
+ mText.setText(license.text);
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/aefyr/sai/model/licenses/License.java b/app/src/main/java/com/aefyr/sai/model/licenses/License.java
new file mode 100644
index 00000000..f4fab0f9
--- /dev/null
+++ b/app/src/main/java/com/aefyr/sai/model/licenses/License.java
@@ -0,0 +1,13 @@
+package com.aefyr.sai.model.licenses;
+
+public class License {
+
+ public String subject;
+ public String text;
+
+ public License(String subject, String text) {
+ this.subject = subject;
+ this.text = text;
+ }
+
+}
diff --git a/app/src/main/java/com/aefyr/sai/ui/activities/AboutActivity.java b/app/src/main/java/com/aefyr/sai/ui/activities/AboutActivity.java
index 00c1ade6..5f65c354 100644
--- a/app/src/main/java/com/aefyr/sai/ui/activities/AboutActivity.java
+++ b/app/src/main/java/com/aefyr/sai/ui/activities/AboutActivity.java
@@ -18,6 +18,7 @@ protected void onCreate(Bundle savedInstanceState) {
((TextView) findViewById(R.id.tv_about_app)).setText(String.format("%s %s", getString(R.string.app_name_full), BuildConfig.VERSION_NAME));
findViewById(R.id.button_about_source).setOnClickListener((v) -> openLink(getString(R.string.about_source_link)));
findViewById(R.id.button_about_donate).setOnClickListener((v) -> openLink(getString(R.string.about_donate_link)));
+ findViewById(R.id.button_about_licenses).setOnClickListener((v) -> startActivity(new Intent(this, LicensesActivity.class)));
}
private void openLink(String link) {
diff --git a/app/src/main/java/com/aefyr/sai/ui/activities/LicensesActivity.java b/app/src/main/java/com/aefyr/sai/ui/activities/LicensesActivity.java
new file mode 100644
index 00000000..d4a16050
--- /dev/null
+++ b/app/src/main/java/com/aefyr/sai/ui/activities/LicensesActivity.java
@@ -0,0 +1,32 @@
+package com.aefyr.sai.ui.activities;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.aefyr.sai.R;
+import com.aefyr.sai.adapters.LicensesAdapter;
+import com.aefyr.sai.viewmodels.LicensesViewModel;
+
+public class LicensesActivity extends ThemedActivity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_licenses);
+
+ RecyclerView recyclerView = findViewById(R.id.rv_licenses);
+
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+ recyclerView.getRecycledViewPool().setMaxRecycledViews(0, 16);
+
+ LicensesAdapter adapter = new LicensesAdapter(this);
+ recyclerView.setAdapter(adapter);
+
+ LicensesViewModel viewModel = ViewModelProviders.of(this).get(LicensesViewModel.class);
+ viewModel.getLicenses().observe(this, adapter::setLicenses);
+ }
+}
diff --git a/app/src/main/java/com/aefyr/sai/utils/IOUtils.java b/app/src/main/java/com/aefyr/sai/utils/IOUtils.java
index fbb9f00f..44b4ebe7 100644
--- a/app/src/main/java/com/aefyr/sai/utils/IOUtils.java
+++ b/app/src/main/java/com/aefyr/sai/utils/IOUtils.java
@@ -4,6 +4,7 @@
import android.util.Log;
import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -11,6 +12,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.nio.charset.Charset;
import java.util.zip.CRC32;
public class IOUtils {
@@ -75,4 +77,11 @@ public static Thread writeStreamToStringBuilder(StringBuilder builder, InputStre
return t;
}
+ public static String readStream(InputStream aInputStream, Charset charset) throws IOException {
+ try (InputStream inputStream = aInputStream; ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+ copyStream(inputStream, outputStream);
+ return new String(outputStream.toByteArray(), charset);
+ }
+ }
+
}
diff --git a/app/src/main/java/com/aefyr/sai/viewmodels/LicensesViewModel.java b/app/src/main/java/com/aefyr/sai/viewmodels/LicensesViewModel.java
new file mode 100644
index 00000000..a5edd525
--- /dev/null
+++ b/app/src/main/java/com/aefyr/sai/viewmodels/LicensesViewModel.java
@@ -0,0 +1,70 @@
+package com.aefyr.sai.viewmodels;
+
+import android.app.Application;
+import android.content.res.AssetManager;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+
+import com.aefyr.sai.model.licenses.License;
+import com.aefyr.sai.utils.IOUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class LicensesViewModel extends AndroidViewModel {
+
+ private MutableLiveData> mLicenses = new MutableLiveData<>();
+ private MutableLiveData mAreLicensesLoading = new MutableLiveData<>();
+
+ public LicensesViewModel(@NonNull Application application) {
+ super(application);
+
+ mLicenses.setValue(Collections.emptyList());
+ mAreLicensesLoading.setValue(false);
+
+ loadLicences();
+ }
+
+ public LiveData> getLicenses() {
+ return mLicenses;
+ }
+
+ public LiveData getAreLicensesLoading() {
+ return mAreLicensesLoading;
+ }
+
+ private void loadLicences() {
+ if (mAreLicensesLoading.getValue())
+ return;
+
+ mAreLicensesLoading.setValue(true);
+
+ new Thread(() -> {
+ try {
+ AssetManager assetManager = getApplication().getAssets();
+ String licensesDir = "licenses";
+
+ String[] rawLicenses = assetManager.list(licensesDir);
+ ArrayList licenses = new ArrayList<>(rawLicenses.length);
+
+ for (String rawLicense : rawLicenses)
+ licenses.add(new License(rawLicense, IOUtils.readStream(assetManager.open(licensesDir + "/" + rawLicense), StandardCharsets.UTF_8)));
+
+ Collections.sort(licenses, (license1, license2) -> license1.subject.compareToIgnoreCase(license2.subject));
+
+ mLicenses.postValue(licenses);
+ mAreLicensesLoading.postValue(false);
+ } catch (Exception e) {
+ Log.wtf("Licenses", e);
+ mAreLicensesLoading.postValue(false);
+ }
+ }).start();
+ }
+
+}
diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml
index 62abba79..4681234f 100644
--- a/app/src/main/res/layout/activity_about.xml
+++ b/app/src/main/res/layout/activity_about.xml
@@ -52,6 +52,12 @@
android:layout_margin="8dp"
android:text="@string/about_source" />
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_license.xml b/app/src/main/res/layout/item_license.xml
new file mode 100644
index 00000000..49cb9747
--- /dev/null
+++ b/app/src/main/res/layout/item_license.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 16d2b92a..0c7c9ae8 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -88,5 +88,6 @@
GitHub
Поддержать
+ Лицензии
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 556964e5..143f2523 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -93,5 +93,6 @@
https://github.com/Aefyr/SAI
Donate
https://yasobe.ru/na/sai
+ Licenses