迁移项目
This commit is contained in:
21
.gitignore
vendored
21
.gitignore
vendored
@@ -1,12 +1,11 @@
|
||||
/build
|
||||
gen
|
||||
.DS_Store
|
||||
/obj
|
||||
/ffmpeg_rtsp
|
||||
.vscode
|
||||
local.properties
|
||||
gradle.properties
|
||||
.gradle
|
||||
.idea
|
||||
*.iml
|
||||
/exo-library
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
/.kotlin
|
||||
@@ -1,16 +1,22 @@
|
||||
apply plugin: 'com.android.application'
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion '28.0.3'
|
||||
namespace "org.easydarwin.easyplayer"
|
||||
compileSdk {
|
||||
version = release(36)
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.easydarwin.easyplayer"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 26
|
||||
applicationId "org.easydarwin.easyplayer.pro"
|
||||
minSdk 28
|
||||
targetSdk 36
|
||||
versionCode 14210703
|
||||
versionName "1.4.21.0703"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
if (project.hasProperty('PLAYER_KEY')) {
|
||||
buildConfigField 'String', 'PLAYER_KEY', PLAYER_KEY
|
||||
} else {
|
||||
@@ -19,44 +25,27 @@ android {
|
||||
}
|
||||
|
||||
ndk {
|
||||
//设置支持的SO库架构
|
||||
// abiFilters 'armeabi', 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
|
||||
abiFilters 'x86', 'armeabi-v7a'
|
||||
abiFilters 'armeabi-v7a'/*, 'arm64-v8a'*/
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
|
||||
dataBinding {
|
||||
enabled = true
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
flavorDimensions "prod"
|
||||
productFlavors {
|
||||
pro {
|
||||
applicationId "org.easydarwin.easyplayer.pro"
|
||||
dimension "prod"
|
||||
}
|
||||
|
||||
/*fastPro {
|
||||
applicationId "org.easydarwin.easyplayer.pro"
|
||||
dimension "prod"
|
||||
}*/
|
||||
|
||||
/*njjl {
|
||||
applicationId "org.easydarwin.easyplayer.pro"
|
||||
dimension "prod"
|
||||
}*/
|
||||
}
|
||||
|
||||
//签名配置
|
||||
signingConfigs {
|
||||
|
||||
buildFeatures {
|
||||
buildConfig true
|
||||
viewBinding true
|
||||
dataBinding true
|
||||
}
|
||||
|
||||
android.applicationVariants.all { variant ->
|
||||
@@ -66,32 +55,19 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs 'libs'
|
||||
}
|
||||
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
|
||||
implementation files('libs/gson-2.1.jar')
|
||||
|
||||
implementation "com.android.support:appcompat-v7:${support_version}"
|
||||
implementation "com.android.support:support-v4:${support_version}"
|
||||
implementation "com.android.support:preference-v7:${support_version}"
|
||||
implementation "com.android.support:design:${support_version}"
|
||||
implementation "com.android.support:cardview-v7:${support_version}"
|
||||
|
||||
// implementation 'com.writingminds:FFmpegAndroid:0.3.2'
|
||||
implementation 'com.github.bumptech.glide:glide:3.7.0'
|
||||
implementation 'com.github.chrisbanes:PhotoView:1.3.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
implementation 'com.budiyev.android:code-scanner:1.9.4'
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
implementation libs.androidx.core.ktx
|
||||
implementation libs.androidx.appcompat
|
||||
implementation libs.androidx.constraintlayout
|
||||
implementation libs.androidx.recyclerview
|
||||
implementation libs.androidx.swiperefreshlayout
|
||||
implementation libs.material.components
|
||||
implementation libs.glide
|
||||
implementation libs.code.scanner
|
||||
implementation project(':ijkplayer-java')
|
||||
implementation project(':photoview')
|
||||
|
||||
testImplementation libs.junit
|
||||
androidTestImplementation libs.androidx.junit
|
||||
androidTestImplementation libs.androidx.espresso.core
|
||||
}
|
||||
|
||||
Binary file not shown.
25
EasyPlayerPro/proguard-rules.pro
vendored
25
EasyPlayerPro/proguard-rules.pro
vendored
@@ -1,30 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in D:\software\adt-bundle-windows-x86_64-20140702\sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
# 忽略警告
|
||||
-ignorewarning
|
||||
|
||||
-keepclassmembers class org.easydarwin.video.EasyRTSPClient {
|
||||
public *;
|
||||
}
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
-keepclassmembers class org.easydarwin.video.RTSPClient {
|
||||
private void onRTSPSourceCallBack(int, int, int, byte[], byte[]);
|
||||
}
|
||||
-keepclassmembers class org.easydarwin.video.RTSPClient$FrameInfo{
|
||||
*;
|
||||
}
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -1,13 +0,0 @@
|
||||
package org.esaydarwin.rtsp.player;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
@@ -33,10 +33,14 @@ import android.opengl.GLES20;
|
||||
import android.opengl.Matrix;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -66,8 +70,8 @@ import java.nio.FloatBuffer;
|
||||
* (This was derived from bits and pieces of CTS tests, and is packaged as such, but is not
|
||||
* currently part of CTS.)
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
public class CameraToMpegTest extends AndroidTestCase {
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class CameraToMpegTest {
|
||||
private static final String TAG = "CameraToMpegTest";
|
||||
private static final boolean VERBOSE = false; // lots of logging
|
||||
|
||||
@@ -104,45 +108,41 @@ public class CameraToMpegTest extends AndroidTestCase {
|
||||
// allocate one of these up front so we don't need to do it every time
|
||||
private MediaCodec.BufferInfo mBufferInfo;
|
||||
|
||||
/** test entry point */
|
||||
public void testEncodeCameraToMp4() throws Throwable {
|
||||
CameraToMpegWrapper.runTest(this);
|
||||
/**
|
||||
* Attempts to find a preview size that matches the provided width and height (which
|
||||
* specify the dimensions of the encoded video). If it fails to find a match it just
|
||||
* uses the default preview size.
|
||||
* <p>
|
||||
* TODO: should do a best-fit match.
|
||||
*/
|
||||
private static void choosePreviewSize(Camera.Parameters parms, int width, int height) {
|
||||
// We should make sure that the requested MPEG size is less than the preferred
|
||||
// size, and has the same aspect ratio.
|
||||
Camera.Size ppsfv = parms.getPreferredPreviewSizeForVideo();
|
||||
if (VERBOSE && ppsfv != null) {
|
||||
Log.d(TAG, "Camera preferred preview size for video is " +
|
||||
ppsfv.width + "x" + ppsfv.height);
|
||||
}
|
||||
|
||||
for (Camera.Size size : parms.getSupportedPreviewSizes()) {
|
||||
if (size.width == width && size.height == height) {
|
||||
parms.setPreviewSize(width, height);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Log.w(TAG, "Unable to set preview size to " + width + "x" + height);
|
||||
if (ppsfv != null) {
|
||||
parms.setPreviewSize(ppsfv.width, ppsfv.height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps encodeCameraToMpeg(). This is necessary because SurfaceTexture will try to use
|
||||
* the looper in the current thread if one exists, and the CTS tests create one on the
|
||||
* test thread.
|
||||
*
|
||||
* The wrapper propagates exceptions thrown by the worker thread back to the caller.
|
||||
* test entry point
|
||||
*/
|
||||
private static class CameraToMpegWrapper implements Runnable {
|
||||
private Throwable mThrowable;
|
||||
private CameraToMpegTest mTest;
|
||||
|
||||
private CameraToMpegWrapper(CameraToMpegTest test) {
|
||||
mTest = test;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
mTest.encodeCameraToMpeg();
|
||||
} catch (Throwable th) {
|
||||
mThrowable = th;
|
||||
}
|
||||
}
|
||||
|
||||
/** Entry point. */
|
||||
public static void runTest(CameraToMpegTest obj) throws Throwable {
|
||||
CameraToMpegWrapper wrapper = new CameraToMpegWrapper(obj);
|
||||
Thread th = new Thread(wrapper, "codec test");
|
||||
th.start();
|
||||
th.join();
|
||||
if (wrapper.mThrowable != null) {
|
||||
throw wrapper.mThrowable;
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testEncodeCameraToMp4() throws Throwable {
|
||||
CameraToMpegWrapper.runTest(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,35 +261,6 @@ public class CameraToMpegTest extends AndroidTestCase {
|
||||
Log.d(TAG, "Camera preview size is " + size.width + "x" + size.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find a preview size that matches the provided width and height (which
|
||||
* specify the dimensions of the encoded video). If it fails to find a match it just
|
||||
* uses the default preview size.
|
||||
* <p>
|
||||
* TODO: should do a best-fit match.
|
||||
*/
|
||||
private static void choosePreviewSize(Camera.Parameters parms, int width, int height) {
|
||||
// We should make sure that the requested MPEG size is less than the preferred
|
||||
// size, and has the same aspect ratio.
|
||||
Camera.Size ppsfv = parms.getPreferredPreviewSizeForVideo();
|
||||
if (VERBOSE && ppsfv != null) {
|
||||
Log.d(TAG, "Camera preferred preview size for video is " +
|
||||
ppsfv.width + "x" + ppsfv.height);
|
||||
}
|
||||
|
||||
for (Camera.Size size : parms.getSupportedPreviewSizes()) {
|
||||
if (size.width == width && size.height == height) {
|
||||
parms.setPreviewSize(width, height);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Log.w(TAG, "Unable to set preview size to " + width + "x" + height);
|
||||
if (ppsfv != null) {
|
||||
parms.setPreviewSize(ppsfv.width, ppsfv.height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops camera preview, and releases the camera to the system.
|
||||
*/
|
||||
@@ -497,6 +468,43 @@ public class CameraToMpegTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps encodeCameraToMpeg(). This is necessary because SurfaceTexture will try to use
|
||||
* the looper in the current thread if one exists, and the CTS tests create one on the
|
||||
* test thread.
|
||||
* <p>
|
||||
* The wrapper propagates exceptions thrown by the worker thread back to the caller.
|
||||
*/
|
||||
private static class CameraToMpegWrapper implements Runnable {
|
||||
private Throwable mThrowable;
|
||||
private CameraToMpegTest mTest;
|
||||
|
||||
private CameraToMpegWrapper(CameraToMpegTest test) {
|
||||
mTest = test;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point.
|
||||
*/
|
||||
public static void runTest(CameraToMpegTest obj) throws Throwable {
|
||||
CameraToMpegWrapper wrapper = new CameraToMpegWrapper(obj);
|
||||
Thread th = new Thread(wrapper, "codec test");
|
||||
th.start();
|
||||
th.join();
|
||||
if (wrapper.mThrowable != null) {
|
||||
throw wrapper.mThrowable;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
mTest.encodeCameraToMpeg();
|
||||
} catch (Throwable th) {
|
||||
mThrowable = th;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds state associated with a Surface used for MediaCodec encoder input.
|
||||
@@ -754,16 +762,6 @@ public class CameraToMpegTest extends AndroidTestCase {
|
||||
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
|
||||
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
|
||||
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
|
||||
private final float[] mTriangleVerticesData = {
|
||||
// X, Y, Z, U, V
|
||||
-1.0f, -1.0f, 0, 0.f, 0.f,
|
||||
1.0f, -1.0f, 0, 1.f, 0.f,
|
||||
-1.0f, 1.0f, 0, 0.f, 1.f,
|
||||
1.0f, 1.0f, 0, 1.f, 1.f,
|
||||
};
|
||||
|
||||
private FloatBuffer mTriangleVertices;
|
||||
|
||||
private static final String VERTEX_SHADER =
|
||||
"uniform mat4 uMVPMatrix;\n" +
|
||||
"uniform mat4 uSTMatrix;\n" +
|
||||
@@ -774,7 +772,6 @@ public class CameraToMpegTest extends AndroidTestCase {
|
||||
" gl_Position = uMVPMatrix * aPosition;\n" +
|
||||
" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
|
||||
"}\n";
|
||||
|
||||
private static final String FRAGMENT_SHADER =
|
||||
"#extension GL_OES_EGL_image_external : require\n" +
|
||||
"precision mediump float;\n" + // highp here doesn't seem to matter
|
||||
@@ -783,7 +780,14 @@ public class CameraToMpegTest extends AndroidTestCase {
|
||||
"void main() {\n" +
|
||||
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
|
||||
"}\n";
|
||||
|
||||
private final float[] mTriangleVerticesData = {
|
||||
// X, Y, Z, U, V
|
||||
-1.0f, -1.0f, 0, 0.f, 0.f,
|
||||
1.0f, -1.0f, 0, 1.f, 0.f,
|
||||
-1.0f, 1.0f, 0, 0.f, 1.f,
|
||||
1.0f, 1.0f, 0, 1.f, 1.f,
|
||||
};
|
||||
private FloatBuffer mTriangleVertices;
|
||||
private float[] mMVPMatrix = new float[16];
|
||||
private float[] mSTMatrix = new float[16];
|
||||
|
||||
@@ -796,13 +800,19 @@ public class CameraToMpegTest extends AndroidTestCase {
|
||||
|
||||
public STextureRender() {
|
||||
mTriangleVertices = ByteBuffer.allocateDirect(
|
||||
mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
|
||||
mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
|
||||
.order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
mTriangleVertices.put(mTriangleVerticesData).position(0);
|
||||
|
||||
Matrix.setIdentityM(mSTMatrix, 0);
|
||||
}
|
||||
|
||||
public static void checkLocation(int location, String label) {
|
||||
if (location < 0) {
|
||||
throw new RuntimeException("Unable to locate '" + label + "' in program");
|
||||
}
|
||||
}
|
||||
|
||||
public int getTextureId() {
|
||||
return mTextureID;
|
||||
}
|
||||
@@ -952,11 +962,5 @@ public class CameraToMpegTest extends AndroidTestCase {
|
||||
throw new RuntimeException(op + ": glError " + error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkLocation(int location, String label) {
|
||||
if (location < 0) {
|
||||
throw new RuntimeException("Unable to locate '" + label + "' in program");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.easydarwin.easyplayer">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_LOGS" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
|
||||
<application
|
||||
android:name=".TheApp"
|
||||
@@ -20,6 +27,7 @@
|
||||
android:icon="@mipmap/ic_launcher_foreground"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<meta-data
|
||||
@@ -31,6 +39,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".PlayListActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
@@ -50,15 +59,18 @@
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:theme="@style/FullscreenTheme" />
|
||||
|
||||
<activity
|
||||
android:name=".AboutActivity" />
|
||||
<activity android:name=".AboutActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:label="@string/title_activity_settings" />
|
||||
|
||||
<activity android:name=".MediaFilesActivity" android:label="文件夹"/>
|
||||
<activity android:name=".ScanQRActivity" android:label="扫码"/>
|
||||
|
||||
<activity
|
||||
android:name=".MediaFilesActivity"
|
||||
android:label="文件夹" />
|
||||
<activity
|
||||
android:name=".ScanQRActivity"
|
||||
android:label="扫码" />
|
||||
|
||||
</application>
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package org.easydarwin.easyplayer;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
|
||||
import org.easydarwin.easyplayer.databinding.ActivityAboutBinding;
|
||||
import org.easydarwin.easyplayer.views.ProVideoView;
|
||||
|
||||
@@ -43,7 +44,7 @@ public class AboutActivity extends AppCompatActivity implements View.OnClickList
|
||||
binding.version.setText("EasyPlayer Pro播放器");
|
||||
binding.version.append("(");
|
||||
|
||||
long activeDays = ProVideoView.getActiveDays(this,BuildConfig.PLAYER_KEY);
|
||||
long activeDays = ProVideoView.getActiveDays(this, BuildConfig.PLAYER_KEY);
|
||||
|
||||
SpannableString ss;
|
||||
if (activeDays >= 9999) {
|
||||
@@ -76,20 +77,17 @@ public class AboutActivity extends AppCompatActivity implements View.OnClickList
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent= new Intent();
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
Uri content_url = Uri.parse("http://www.easydarwin.org");
|
||||
|
||||
switch (v.getId()) {
|
||||
case R.id.darwin_content_tv:
|
||||
content_url = Uri.parse("http://www.easydarwin.org");
|
||||
break;
|
||||
case R.id.dss_content_tv:
|
||||
content_url = Uri.parse("http://www.easydss.com");
|
||||
break;
|
||||
case R.id.nvr_content_tv:
|
||||
content_url = Uri.parse("http://www.easynvr.com");
|
||||
break;
|
||||
int id = v.getId();
|
||||
if (id == R.id.darwin_content_tv) {
|
||||
content_url = Uri.parse("http://www.easydarwin.org");
|
||||
} else if (id == R.id.dss_content_tv) {
|
||||
content_url = Uri.parse("http://www.easydss.com");
|
||||
} else if (id == R.id.nvr_content_tv) {
|
||||
content_url = Uri.parse("http://www.easynvr.com");
|
||||
}
|
||||
|
||||
intent.setData(content_url);
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
package org.easydarwin.easyplayer;
|
||||
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
@@ -15,12 +10,19 @@ import android.text.style.RelativeSizeSpan;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
|
||||
import org.easydarwin.easyplayer.databinding.ActivityMediaFilesBinding;
|
||||
import org.easydarwin.easyplayer.fragments.LocalFileFragment;
|
||||
|
||||
/**
|
||||
* 录像和截图
|
||||
* */
|
||||
*
|
||||
*/
|
||||
public class MediaFilesActivity extends AppCompatActivity {
|
||||
|
||||
private ActivityMediaFilesBinding mDataBinding;
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
package org.easydarwin.easyplayer;
|
||||
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -27,8 +22,15 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.signature.StringSignature;
|
||||
|
||||
import org.easydarwin.easyplayer.data.VideoSource;
|
||||
import org.easydarwin.easyplayer.databinding.ActivityPlayListBinding;
|
||||
@@ -40,21 +42,18 @@ import org.easydarwin.easyplayer.views.ProVideoView;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
/**
|
||||
* 视频广场
|
||||
* */
|
||||
*
|
||||
*/
|
||||
@SuppressLint("Range")
|
||||
public class PlayListActivity extends AppCompatActivity implements View.OnClickListener, View.OnLongClickListener {
|
||||
|
||||
private static final int REQUEST_PLAY = 1000;
|
||||
public static final int REQUEST_CAMERA_PERMISSION = 1001;
|
||||
private static final int REQUEST_SCAN_TEXT_URL = 1003; // 扫描二维码
|
||||
|
||||
public static final String EXTRA_BOOLEAN_SELECT_ITEM_TO_PLAY = "extra-boolean-select-item-to-play";
|
||||
|
||||
private static final int REQUEST_PLAY = 1000;
|
||||
private static final int REQUEST_SCAN_TEXT_URL = 1003; // 扫描二维码
|
||||
private int mPos;
|
||||
private ActivityPlayListBinding mBinding;
|
||||
private RecyclerView mRecyclerView;
|
||||
@@ -83,9 +82,7 @@ public class PlayListActivity extends AppCompatActivity implements View.OnClickL
|
||||
mCursor = TheApp.sDB.query(VideoSource.TABLE_NAME, null, null, null, null, null, null);
|
||||
if (!mCursor.moveToFirst()) {
|
||||
List<String> urls = new ArrayList<>();
|
||||
urls.add("rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov");
|
||||
urls.add("rtmp://live.hkstv.hk.lxdns.com/live/hks2");
|
||||
urls.add("http://www.easydarwin.org/public/video/3/video.m3u8");
|
||||
urls.add("rtsp://77.110.228.219/axis-media/media.amp");
|
||||
urls.add("http://m4.pptvyun.com/pvod/e11a0/ijblO6coKRX6a8NEQgg8LDZcqPY/eyJkbCI6MTUxNjYyNTM3NSwiZXMiOjYwNDgwMCwiaWQiOiIwYTJkbnEtWG82S2VvcTZMNEsyZG9hZmhvNkNjbTY2WXB3IiwidiI6IjEuMCJ9/0a2dnq-Xo6Keoq6L4K2doafho6Ccm66Ypw.mp4");
|
||||
|
||||
for (String url : urls) {
|
||||
@@ -127,7 +124,6 @@ public class PlayListActivity extends AppCompatActivity implements View.OnClickL
|
||||
|
||||
Glide.with(PlayListActivity.this)
|
||||
.load(file)
|
||||
.signature(new StringSignature(UUID.randomUUID().toString()))
|
||||
.placeholder(R.drawable.placeholder)
|
||||
.centerCrop()
|
||||
.into(plvh.mImageView);
|
||||
@@ -192,9 +188,10 @@ public class PlayListActivity extends AppCompatActivity implements View.OnClickL
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
switch (requestCode) {
|
||||
case REQUEST_CAMERA_PERMISSION: {
|
||||
if (grantResults.length > 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
|
||||
if (grantResults.length > 1 && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) {
|
||||
toScanQRActivity();
|
||||
}
|
||||
|
||||
@@ -310,9 +307,9 @@ public class PlayListActivity extends AppCompatActivity implements View.OnClickL
|
||||
}
|
||||
|
||||
if (url.toLowerCase().indexOf("rtsp://") != 0 && url.toLowerCase().indexOf("rtmp://") != 0 &&
|
||||
url.toLowerCase().indexOf("http://") != 0 && url.toLowerCase().indexOf("https://") != 0 &&
|
||||
url.toLowerCase().indexOf("http://") != 0 && url.toLowerCase().indexOf("https://") != 0 &&
|
||||
url.toLowerCase().indexOf("hls://") != 0) {
|
||||
Toast.makeText(PlayListActivity.this,"不是合法的地址,请重新添加.",Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(PlayListActivity.this, "不是合法的地址,请重新添加.", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -361,7 +358,7 @@ public class PlayListActivity extends AppCompatActivity implements View.OnClickL
|
||||
private void notifyAboutColorChange() {
|
||||
//// !!!! important to set KEY !!!!
|
||||
ProVideoView.setKey(BuildConfig.PLAYER_KEY);
|
||||
long activeDays = ProVideoView.getActiveDays(this,BuildConfig.PLAYER_KEY);
|
||||
long activeDays = ProVideoView.getActiveDays(this, BuildConfig.PLAYER_KEY);
|
||||
|
||||
ImageView iv = findViewById(R.id.toolbar_about);
|
||||
|
||||
@@ -379,9 +376,25 @@ public class PlayListActivity extends AppCompatActivity implements View.OnClickL
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode == REQUEST_SCAN_TEXT_URL) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
String url = data.getStringExtra("text");
|
||||
edit.setText(url);
|
||||
}
|
||||
} else {
|
||||
// mRecyclerView.getAdapter().notifyItemChanged(mPos);
|
||||
mRecyclerView.getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频源的item
|
||||
* */
|
||||
*
|
||||
*/
|
||||
class PlayListViewHolder extends RecyclerView.ViewHolder {
|
||||
private final TextView mTextView;
|
||||
private final TextView mAudienceNumber;
|
||||
@@ -399,19 +412,4 @@ public class PlayListActivity extends AppCompatActivity implements View.OnClickL
|
||||
itemView.setTag(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode == REQUEST_SCAN_TEXT_URL) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
String url = data.getStringExtra("text");
|
||||
edit.setText(url);
|
||||
}
|
||||
} else {
|
||||
// mRecyclerView.getAdapter().notifyItemChanged(mPos);
|
||||
mRecyclerView.getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,19 @@ package org.easydarwin.easyplayer;
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.graphics.Color;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.view.ViewConfigurationCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
@@ -45,6 +40,13 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.ViewConfigurationCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
|
||||
import org.easydarwin.easyplayer.databinding.ActivityMainProBinding;
|
||||
@@ -60,13 +62,9 @@ import java.util.Date;
|
||||
import tv.danmaku.ijk.media.player.IMediaPlayer;
|
||||
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
|
||||
|
||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
|
||||
public class ProVideoActivity extends AppCompatActivity {
|
||||
private static final String TAG = "ProVideoActivity";
|
||||
|
||||
public static final int REQUEST_WRITE_STORAGE = 111;
|
||||
|
||||
private static final String TAG = "ProVideoActivity";
|
||||
private String mVideoPath;
|
||||
private Uri mVideoUri;
|
||||
|
||||
@@ -315,8 +313,8 @@ public class ProVideoActivity extends AppCompatActivity {
|
||||
TextView view = (TextView) findViewById(R.id.loading_speed);
|
||||
view.setText(String.format("%3.01fKB/s", received * 1.0f / 1024));
|
||||
|
||||
if (findViewById(android.R.id.progress).getVisibility() == View.VISIBLE){
|
||||
mVideoView.postDelayed(this,1000);
|
||||
if (findViewById(android.R.id.progress).getVisibility() == View.VISIBLE) {
|
||||
mVideoView.postDelayed(this, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -368,7 +366,7 @@ public class ProVideoActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (REQUEST_WRITE_STORAGE == requestCode){
|
||||
if (REQUEST_WRITE_STORAGE == requestCode) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
doTakePicture();
|
||||
}
|
||||
@@ -426,11 +424,11 @@ public class ProVideoActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
/*
|
||||
* 截图
|
||||
* */
|
||||
* 截图
|
||||
* */
|
||||
public void onTakePicture(View view) {
|
||||
if (mVideoView.isInPlaybackState()) {
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE);
|
||||
} else {
|
||||
doTakePicture();
|
||||
@@ -446,7 +444,7 @@ public class ProVideoActivity extends AppCompatActivity {
|
||||
final String picture = mVideoView.takePicture(file.getPath());
|
||||
|
||||
if (!TextUtils.isEmpty(picture)) {
|
||||
Toast.makeText(ProVideoActivity.this,"图片已保存", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(ProVideoActivity.this, "图片已保存", Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (mScanner == null) {
|
||||
MediaScannerConnection connection = new MediaScannerConnection(ProVideoActivity.this, new MediaScannerConnection.MediaScannerConnectionClient() {
|
||||
|
||||
@@ -2,11 +2,12 @@ package org.easydarwin.easyplayer;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.budiyev.android.codescanner.CodeScanner;
|
||||
import com.budiyev.android.codescanner.CodeScannerView;
|
||||
import com.budiyev.android.codescanner.DecodeCallback;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package org.easydarwin.easyplayer;
|
||||
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
|
||||
import org.easydarwin.easyplayer.databinding.ActivitySettingBinding;
|
||||
import org.easydarwin.easyplayer.util.SPUtil;
|
||||
|
||||
|
||||
@@ -4,12 +4,13 @@ import android.annotation.SuppressLint;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* 启动页
|
||||
*/
|
||||
@@ -53,7 +54,6 @@ public class SplashActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
};
|
||||
private boolean mVisible;
|
||||
private final Runnable mHideRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -74,6 +74,7 @@ public class SplashActivity extends AppCompatActivity {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
private boolean mVisible;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
@@ -2,14 +2,8 @@ package org.easydarwin.easyplayer.fragments;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -20,9 +14,15 @@ import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
|
||||
import org.easydarwin.easyplayer.PlayListActivity;
|
||||
import org.easydarwin.easyplayer.ProVideoActivity;
|
||||
import org.easydarwin.easyplayer.R;
|
||||
import org.easydarwin.easyplayer.databinding.FragmentMediaFileBinding;
|
||||
@@ -34,16 +34,13 @@ import java.io.FilenameFilter;
|
||||
|
||||
public class LocalFileFragment extends Fragment implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {
|
||||
public static final String KEY_IS_RECORD = "key_last_selection";
|
||||
|
||||
private boolean mShowMp4File;
|
||||
private FragmentMediaFileBinding mBinding;
|
||||
|
||||
SparseArray<Boolean> mImageChecked;
|
||||
|
||||
private String mSuffix;
|
||||
File mRoot = null;
|
||||
File[] mSubFiles;
|
||||
int mImgHeight;
|
||||
private boolean mShowMp4File;
|
||||
private FragmentMediaFileBinding mBinding;
|
||||
private String mSuffix;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package org.easydarwin.easyplayer.views;
|
||||
|
||||
import static tv.danmaku.ijk.media.player.IjkMediaPlayer.native_active_days;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
import org.easydarwin.easyplayer.ProVideoActivity;
|
||||
import org.easydarwin.easyplayer.util.FileUtil;
|
||||
|
||||
@@ -18,11 +21,9 @@ import java.util.Date;
|
||||
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
|
||||
import tv.danmaku.ijk.media.widget.media.IjkVideoView;
|
||||
|
||||
import static tv.danmaku.ijk.media.player.IjkMediaPlayer.native_active_days;
|
||||
|
||||
/**
|
||||
* 播放器
|
||||
*
|
||||
* <p>
|
||||
* Created by apple on 2017/2/11.
|
||||
*/
|
||||
public class ProVideoView extends IjkVideoView implements VideoControllerView.FullScreenAbleMediaPlayerControl {
|
||||
@@ -53,19 +54,21 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
|
||||
return native_active_days(context, key);
|
||||
}
|
||||
|
||||
/** ================ super override ================ */
|
||||
/**
|
||||
* ================ super override ================
|
||||
*/
|
||||
|
||||
public void startRecord(String path, int seconds) {
|
||||
if (mMediaPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.startRecord(path,seconds);
|
||||
super.startRecord(path, seconds);
|
||||
mRecordPath = path;
|
||||
}
|
||||
|
||||
public void stopRecord() {
|
||||
if (mMediaPlayer == null){
|
||||
if (mMediaPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -73,7 +76,9 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
|
||||
mRecordPath = null;
|
||||
}
|
||||
|
||||
/** ================ FullScreenAbleMediaPlayerControl ================ */
|
||||
/**
|
||||
* ================ FullScreenAbleMediaPlayerControl ================
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean isFullScreen() {
|
||||
@@ -131,7 +136,7 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
|
||||
@Override
|
||||
public void reStart() {
|
||||
super.reStart();
|
||||
if (mRecordPath != null){
|
||||
if (mRecordPath != null) {
|
||||
toggleRecord();
|
||||
toggleRecord();
|
||||
}
|
||||
@@ -142,8 +147,8 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
|
||||
if (getContext() instanceof ProVideoActivity) {
|
||||
ProVideoActivity pro = (ProVideoActivity) getContext();
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(pro, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
|
||||
ActivityCompat.requestPermissions(pro, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, ProVideoActivity.REQUEST_WRITE_STORAGE +1);
|
||||
if (ActivityCompat.checkSelfPermission(pro, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(pro, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, ProVideoActivity.REQUEST_WRITE_STORAGE + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -184,8 +189,8 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
|
||||
|
||||
@Override
|
||||
public void setSpeed(float speed) {
|
||||
if (mMediaPlayer == null ) {
|
||||
return ;
|
||||
if (mMediaPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mMediaPlayer instanceof IjkMediaPlayer) {
|
||||
@@ -196,7 +201,7 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
|
||||
|
||||
@Override
|
||||
public void takePicture() {
|
||||
if (getContext() instanceof ProVideoActivity){
|
||||
if (getContext() instanceof ProVideoActivity) {
|
||||
ProVideoActivity pro = (ProVideoActivity) getContext();
|
||||
pro.onTakePicture(null);
|
||||
}
|
||||
|
||||
@@ -3,12 +3,11 @@ package org.easydarwin.easyplayer.views;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* Created by John on 2014/11/11.
|
||||
*/
|
||||
public class SquareImageView extends ImageView {
|
||||
public class SquareImageView extends androidx.appcompat.widget.AppCompatImageView {
|
||||
|
||||
public SquareImageView(Context context) {
|
||||
super(context);
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<layout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/colorWhite">
|
||||
android:background="@color/colorWhite"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="66dp"
|
||||
@@ -24,33 +22,33 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="版本信息"
|
||||
android:gravity="center"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="18sp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="12dp"/>
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:gravity="center"
|
||||
android:text="版本信息"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/toolbar_back"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:src="@drawable/new_nav_back"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="0dp"/>
|
||||
android:layout_marginBottom="0dp"
|
||||
android:src="@drawable/new_nav_back" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
@@ -69,17 +67,17 @@
|
||||
android:id="@+id/desc"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/about_info"
|
||||
android:textSize="15sp"
|
||||
android:lineSpacingExtra="5dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/version"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginRight="16dp" />
|
||||
android:layout_marginRight="16dp"
|
||||
android:lineSpacingExtra="5dp"
|
||||
android:text="@string/about_info"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/version" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/darwin_tv"
|
||||
@@ -102,8 +100,8 @@
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:text="http://www.easydarwin.org"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/colorTheme2"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/darwin_tv" />
|
||||
@@ -129,8 +127,8 @@
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:text="http://www.easydss.com"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/colorTheme2"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dss_tv" />
|
||||
@@ -173,18 +171,18 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/nvr_content_tv" />
|
||||
|
||||
<TextView
|
||||
android:text="Copyright @ Open.TSINGSEE.com"
|
||||
android:layout_height="40dp"
|
||||
android:layout_width="0dp"
|
||||
android:gravity="center"
|
||||
android:id="@+id/textView3"
|
||||
android:background="@color/colorTheme2"
|
||||
android:textColor="#FFFFFF"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="30dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView"
|
||||
android:background="@color/colorTheme2"
|
||||
android:gravity="center"
|
||||
android:text="Copyright @ Open.TSINGSEE.com"
|
||||
android:textColor="#FFFFFF"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -9,24 +9,24 @@
|
||||
tools:context="org.easydarwin.easyplayer.PlayActivity">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/render_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/render_container"
|
||||
android:layout_gravity="center"
|
||||
android:background="#000000">
|
||||
|
||||
<org.easydarwin.easyplayer.views.ProVideoView
|
||||
android:id="@+id/video_view2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true"
|
||||
android:visibility="gone"
|
||||
android:layout_height="match_parent" />
|
||||
android:visibility="gone" />
|
||||
|
||||
<org.easydarwin.easyplayer.views.ProVideoView
|
||||
android:id="@+id/video_view"
|
||||
android:layout_width="match_parent"
|
||||
android:keepScreenOn="true"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/surface_cover"
|
||||
@@ -40,8 +40,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:background="@color/white"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ProgressBar
|
||||
@@ -51,12 +51,12 @@
|
||||
android:indeterminateDrawable="@drawable/anim" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:text="加载中"
|
||||
android:id="@+id/loading_speed"
|
||||
android:textColor="@color/colorTheme"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_height="wrap_content" />
|
||||
android:text="加载中"
|
||||
android:textColor="@color/colorTheme" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -77,16 +77,16 @@
|
||||
android:id="@+id/player_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:background="#fff"
|
||||
android:layout_gravity="center"
|
||||
android:background="#fff"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/new_lost"/>
|
||||
android:src="@drawable/new_lost" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/colorWhite">
|
||||
android:background="@color/colorWhite"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="66dp"
|
||||
@@ -22,42 +22,42 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="文件夹"
|
||||
android:gravity="center"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="18sp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="12dp"/>
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:gravity="center"
|
||||
android:text="文件夹"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/toolbar_back"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:src="@drawable/new_nav_back"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="0dp"/>
|
||||
android:layout_marginBottom="0dp"
|
||||
android:src="@drawable/new_nav_back" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v4.view.PagerTitleStrip
|
||||
<androidx.viewpager.widget.PagerTitleStrip
|
||||
android:id="@+id/pager_title_strip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#f2f2f2"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:background="#f2f2f2"
|
||||
android:textAlignment="center"
|
||||
android:textSize="16sp" />
|
||||
</android.support.v4.view.ViewPager>
|
||||
</androidx.viewpager.widget.ViewPager>
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout>
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<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="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="#ffffff"
|
||||
android:orientation="vertical"
|
||||
tools:context="org.easydarwin.easyplayer.activity.PlayListActivity">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="66dp"
|
||||
@@ -24,27 +22,27 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="EasyPlayer Pro"
|
||||
android:gravity="center"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="18sp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="12dp"/>
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:gravity="center"
|
||||
android:text="EasyPlayer Pro"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/toolbar_about"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:src="@drawable/new_version1"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="0dp"/>
|
||||
android:layout_marginBottom="0dp"
|
||||
android:src="@drawable/new_version1" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottom_ll"
|
||||
@@ -56,64 +54,64 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toolbar_add"
|
||||
android:layout_height="match_parent"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:text="地址"
|
||||
android:textColor="@drawable/new_color_text"
|
||||
android:textSize="13sp"
|
||||
android:drawableTop="@drawable/new_address_btn"
|
||||
android:paddingTop="8dp"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_gravity="end" />
|
||||
android:text="地址"
|
||||
android:textColor="@drawable/new_color_text"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toolbar_file"
|
||||
android:layout_height="match_parent"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:drawableTop="@drawable/new_file_btn"
|
||||
android:onClick="fileList"
|
||||
android:paddingTop="8dp"
|
||||
android:text="文件夹"
|
||||
android:textColor="@drawable/new_color_text"
|
||||
android:textSize="13sp"
|
||||
android:drawableTop="@drawable/new_file_btn"
|
||||
android:paddingTop="8dp"
|
||||
android:onClick="fileList"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_gravity="end" />
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toolbar_setting"
|
||||
android:layout_height="match_parent"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:text="设置"
|
||||
android:textColor="@drawable/new_color_text"
|
||||
android:textSize="13sp"
|
||||
android:drawableTop="@drawable/new_setting_btn"
|
||||
android:paddingTop="8dp"
|
||||
style="@style/Base.Widget.AppCompat.ActionButton"
|
||||
android:layout_gravity="end" />
|
||||
android:text="设置"
|
||||
android:textColor="@drawable/new_color_text"
|
||||
android:textSize="13sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/pull_to_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/toolbar"
|
||||
android:layout_above="@id/bottom_ll">
|
||||
android:layout_above="@id/bottom_ll"
|
||||
android:layout_below="@id/toolbar">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</FrameLayout>
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@@ -13,19 +12,19 @@
|
||||
app:autoFocusButtonVisible="false"
|
||||
app:flashButtonColor="@android:color/white"
|
||||
app:flashButtonVisible="true"
|
||||
app:frameAspectRatioHeight="1"
|
||||
app:frameAspectRatioWidth="1"
|
||||
app:frameColor="@android:color/white"
|
||||
app:frameCornersSize="50dp"
|
||||
app:frameAspectRatioWidth="1"
|
||||
app:frameAspectRatioHeight="1"
|
||||
app:frameSize="0.75"
|
||||
app:frameThickness="2dp"
|
||||
app:maskColor="#66000000"/>
|
||||
app:maskColor="#66000000" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="56dp"
|
||||
android:src="@drawable/new_nav_back"
|
||||
android:padding="18dp"
|
||||
android:layout_height="56dp"
|
||||
android:onClick="onClose"
|
||||
android:layout_height="56dp" />
|
||||
android:padding="18dp"
|
||||
android:src="@drawable/new_nav_back" />
|
||||
|
||||
</FrameLayout>
|
||||
@@ -9,7 +9,7 @@
|
||||
android:background="@color/colorWhite"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="66dp"
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="40dp"
|
||||
android:gravity="center"
|
||||
android:text="EasyPlayer Pro"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="20sp"
|
||||
android:text="EasyPlayer Pro" />
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_copyright"
|
||||
@@ -30,21 +30,19 @@
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:gravity="center"
|
||||
android:text="Copyright @ Open.TSINGSEE.com"
|
||||
android:textColor="#666"
|
||||
android:textSize="12sp"
|
||||
android:text="Copyright @ Open.TSINGSEE.com" />
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/txt_copyright"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:text="EasyPlayer 1.0.0"
|
||||
android:textColor="#666"
|
||||
android:textSize="12sp"
|
||||
android:text="EasyPlayer 1.0.0" />
|
||||
|
||||
|
||||
android:textSize="12sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="128dp"
|
||||
android:layout_margin="1dp"
|
||||
android:background="#666"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="#666"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<ImageView
|
||||
@@ -19,7 +19,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/new_player"/>
|
||||
android:src="@drawable/new_player" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/image_checkbox"
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/media_controller_ll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/media_controller_ll"
|
||||
android:background="#6000"
|
||||
android:orientation="vertical">
|
||||
|
||||
@@ -17,26 +16,26 @@
|
||||
android:id="@+id/tv_speed"
|
||||
style="@style/Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:textColor="@color/white" />
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_fps"
|
||||
style="@style/Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white" />
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_kbps"
|
||||
style="@style/Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/white"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
@@ -49,38 +48,38 @@
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/slow"
|
||||
android:layout_weight="1"
|
||||
style="@android:style/MediaButton.Next"
|
||||
android:src="@drawable/new_slow_btn"
|
||||
android:contentDescription="@string/description" />
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/description"
|
||||
android:src="@drawable/new_slow_btn" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/rewind"
|
||||
android:layout_weight="1"
|
||||
style="@android:style/MediaButton.Rew"
|
||||
android:src="@drawable/new_moveback_btn"
|
||||
android:contentDescription="@string/description" />
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/description"
|
||||
android:src="@drawable/new_moveback_btn" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/pause"
|
||||
android:layout_weight="1"
|
||||
style="@android:style/MediaButton.Play"
|
||||
android:src="@drawable/new_stop_white"
|
||||
android:contentDescription="@string/description" />
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/description"
|
||||
android:src="@drawable/new_stop_white" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/fast_forward"
|
||||
android:layout_weight="1"
|
||||
style="@android:style/MediaButton.Ffwd"
|
||||
android:src="@drawable/new_forward_btn"
|
||||
android:contentDescription="@string/description" />
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/description"
|
||||
android:src="@drawable/new_forward_btn" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/fast"
|
||||
android:layout_weight="1"
|
||||
style="@android:style/MediaButton.Ffwd"
|
||||
android:src="@drawable/new_fast_btn"
|
||||
android:contentDescription="@string/description" />
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/description"
|
||||
android:src="@drawable/new_fast_btn" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -95,52 +94,52 @@
|
||||
android:id="@+id/action_take_picture"
|
||||
style="@style/Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:src="@drawable/new_snapshot_btn" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/action_record"
|
||||
style="@style/Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:src="@drawable/new_videotape_btn" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_record_time"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
android:textColor="#ff0000"
|
||||
android:drawablePadding="5dp"
|
||||
android:layout_weight="1"
|
||||
android:drawableLeft="@drawable/red_dot"
|
||||
android:text="00:00" />
|
||||
android:drawablePadding="5dp"
|
||||
android:gravity="center"
|
||||
android:text="00:00"
|
||||
android:textColor="#ff0000"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/action_change_mode"
|
||||
style="@style/Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:src="@drawable/new_stretch_btn" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/fullscreen"
|
||||
style="@style/Widget.AppCompat.ActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:src="@drawable/new_full" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/seek_bar_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:id="@+id/seek_bar_container"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
@@ -150,20 +149,20 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:paddingLeft="4dip"
|
||||
android:paddingRight="4dip"
|
||||
android:paddingTop="4dip"
|
||||
android:textSize="14sp"
|
||||
android:paddingRight="4dip"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/media_controller_progress"
|
||||
style="@style/CustomSeekbarStyle"
|
||||
android:progress="10"
|
||||
android:secondaryProgress="60"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
android:layout_weight="1"
|
||||
android:progress="10"
|
||||
android:secondaryProgress="60" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/total_time"
|
||||
@@ -171,9 +170,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:paddingLeft="4dip"
|
||||
android:textColor="@color/white"
|
||||
android:paddingRight="4dip"
|
||||
android:paddingTop="4dip"
|
||||
android:paddingRight="4dip"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorWhite">
|
||||
@@ -11,12 +9,12 @@
|
||||
android:id="@+id/new_media_scan"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/new_scan_btn"
|
||||
android:background="@null"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_marginRight="8dp"
|
||||
app:layout_constraintTop_toTopOf="@id/new_media_source_url"
|
||||
app:layout_constraintBottom_toBottomOf="@id/new_media_source_url" />
|
||||
android:background="@null"
|
||||
android:src="@drawable/new_scan_btn"
|
||||
app:layout_constraintBottom_toBottomOf="@id/new_media_source_url"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/new_media_source_url" />
|
||||
|
||||
|
||||
<EditText
|
||||
@@ -32,4 +30,4 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,13 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout>
|
||||
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="240dp"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin">
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -32,10 +31,10 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxHeight="40dp"
|
||||
android:minHeight="40dp"
|
||||
android:ellipsize="end"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:text="9"
|
||||
@@ -55,5 +54,5 @@
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
</android.support.v7.widget.CardView>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</layout>
|
||||
24
build.gradle
24
build.gradle
@@ -1,22 +1,4 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
}
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.android.library) apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven { url "https://jitpack.io" }
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
||||
ext{
|
||||
support_version='26.1.0'
|
||||
}
|
||||
23
gradle.properties
Normal file
23
gradle.properties
Normal file
@@ -0,0 +1,23 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. For more details, visit
|
||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
30
gradle/libs.versions.toml
Normal file
30
gradle/libs.versions.toml
Normal file
@@ -0,0 +1,30 @@
|
||||
[versions]
|
||||
agp = "8.13.1"
|
||||
coreKtx = "1.17.0"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.3.0"
|
||||
espressoCore = "3.7.0"
|
||||
appcompat = "1.7.1"
|
||||
constraintlayout = "2.2.1"
|
||||
recyclerview = "1.4.0"
|
||||
swiperefreshlayout = "1.2.0"
|
||||
materialComponents = "1.13.0"
|
||||
glide = "5.0.5"
|
||||
code-scanner = "2.3.0"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||
androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
|
||||
androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
|
||||
material-components = { group = "com.google.android.material", name = "material", version.ref = "materialComponents" }
|
||||
glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide" }
|
||||
code-scanner = { group = "com.github.yuriy-budiyev", name = "code-scanner", version.ref = "code-scanner" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
android-library = { id = "com.android.library", version.ref = "agp" }
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,7 @@
|
||||
#Sat Apr 06 13:56:34 CST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||
|
||||
319
gradlew
vendored
319
gradlew
vendored
@@ -1,74 +1,129 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# https://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.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn ( ) {
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die ( ) {
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
@@ -77,84 +132,120 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
90
gradlew.bat
vendored
90
gradlew.bat
vendored
@@ -1,4 +1,22 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -8,26 +26,30 @@
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -35,54 +57,36 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
apply plugin: 'com.android.library'
|
||||
plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
namespace "tv.danmaku.ijk.media.player"
|
||||
compileSdk {
|
||||
version = release(36)
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 26
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
versionCode 38
|
||||
versionName "1.1.17.1124"
|
||||
minSdk 28
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
buildToolsVersion '28.0.3'
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
}
|
||||
|
||||
|
||||
11
ijkplayer-java/consumer-rules.pro
Normal file
11
ijkplayer-java/consumer-rules.pro
Normal file
@@ -0,0 +1,11 @@
|
||||
-keepparameternames
|
||||
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,EnclosingMethod
|
||||
-keep class tv.danmaku.ijk.media.widget.media.IjkVideoView {
|
||||
public protected *;
|
||||
}
|
||||
-keep class tv.danmaku.ijk.media.widget.media.IMediaController {
|
||||
public protected *;
|
||||
}
|
||||
-keep class tv.danmaku.ijk.media.player.** {
|
||||
*;
|
||||
}
|
||||
26
ijkplayer-java/proguard-rules.pro
vendored
26
ijkplayer-java/proguard-rules.pro
vendored
@@ -1,31 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /opt/android/ADK/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
-keepparameternames
|
||||
-renamesourcefileattribute SourceFile
|
||||
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
|
||||
|
||||
-keep class tv.danmaku.ijk.media.widget.media.IjkVideoView {
|
||||
public protected *;
|
||||
}
|
||||
-keep class tv.danmaku.ijk.media.widget.media.IMediaController {
|
||||
public protected *;
|
||||
}
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
-keep class tv.danmaku.ijk.media.player.** {
|
||||
*;
|
||||
}
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -1,13 +0,0 @@
|
||||
package tv.danmaku.ijk.media.player;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="java"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>ijkplayer-java</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -1,4 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
@@ -1,4 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="tv.danmaku.ijk.media.player" >
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
@@ -1,15 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-22
|
||||
android.library=true
|
||||
@@ -1,203 +0,0 @@
|
||||
ECLIPSE ANDROID PROJECT IMPORT SUMMARY
|
||||
======================================
|
||||
|
||||
Manifest Merging:
|
||||
-----------------
|
||||
Your project uses libraries that provide manifests, and your Eclipse
|
||||
project did not explicitly turn on manifest merging. In Android Gradle
|
||||
projects, manifests are always merged (meaning that contents from your
|
||||
libraries' manifests will be merged into the app manifest. If you had
|
||||
manually copied contents from library manifests into your app manifest
|
||||
you may need to remove these for the app to build correctly.
|
||||
|
||||
Ignored Files:
|
||||
--------------
|
||||
The following files were *not* copied into the new Gradle project; you
|
||||
should evaluate whether these are still needed in your project and if
|
||||
so manually move them:
|
||||
|
||||
From MediaUploader:
|
||||
* .idea\
|
||||
* .idea\.name
|
||||
* .idea\MediaUploader.iml
|
||||
* .idea\compiler.xml
|
||||
* .idea\copyright\
|
||||
* .idea\copyright\profiles_settings.xml
|
||||
* .idea\encodings.xml
|
||||
* .idea\misc.xml
|
||||
* .idea\modules.xml
|
||||
* .idea\vcs.xml
|
||||
* .idea\workspace.xml
|
||||
* ic_launcher-web.png
|
||||
* proguard-project.txt
|
||||
From libstreaming:
|
||||
* .gitignore
|
||||
* LICENSE
|
||||
* README.md
|
||||
* build.xml
|
||||
* doc\
|
||||
* doc\allclasses-frame.html
|
||||
* doc\allclasses-noframe.html
|
||||
* doc\constant-values.html
|
||||
* doc\deprecated-list.html
|
||||
* doc\help-doc.html
|
||||
* doc\index-all.html
|
||||
* doc\index.html
|
||||
* doc\net\
|
||||
* doc\net\majorkernelpanic\
|
||||
* doc\net\majorkernelpanic\streaming\
|
||||
* doc\net\majorkernelpanic\streaming\MediaStream.html
|
||||
* doc\net\majorkernelpanic\streaming\Session.Callback.html
|
||||
* doc\net\majorkernelpanic\streaming\Session.html
|
||||
* doc\net\majorkernelpanic\streaming\SessionBuilder.html
|
||||
* doc\net\majorkernelpanic\streaming\Stream.html
|
||||
* doc\net\majorkernelpanic\streaming\audio\
|
||||
* doc\net\majorkernelpanic\streaming\audio\AACStream.html
|
||||
* doc\net\majorkernelpanic\streaming\audio\AMRNBStream.html
|
||||
* doc\net\majorkernelpanic\streaming\audio\AudioQuality.html
|
||||
* doc\net\majorkernelpanic\streaming\audio\AudioStream.html
|
||||
* doc\net\majorkernelpanic\streaming\audio\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\audio\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\audio\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\exceptions\
|
||||
* doc\net\majorkernelpanic\streaming\exceptions\CameraInUseException.html
|
||||
* doc\net\majorkernelpanic\streaming\exceptions\ConfNotSupportedException.html
|
||||
* doc\net\majorkernelpanic\streaming\exceptions\InvalidSurfaceException.html
|
||||
* doc\net\majorkernelpanic\streaming\exceptions\StorageUnavailableException.html
|
||||
* doc\net\majorkernelpanic\streaming\exceptions\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\exceptions\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\exceptions\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\gl\
|
||||
* doc\net\majorkernelpanic\streaming\gl\SurfaceManager.html
|
||||
* doc\net\majorkernelpanic\streaming\gl\SurfaceView.ViewAspectRatioMeasurer.html
|
||||
* doc\net\majorkernelpanic\streaming\gl\SurfaceView.html
|
||||
* doc\net\majorkernelpanic\streaming\gl\TextureManager.html
|
||||
* doc\net\majorkernelpanic\streaming\gl\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\gl\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\gl\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\hw\
|
||||
* doc\net\majorkernelpanic\streaming\hw\CodecManager.html
|
||||
* doc\net\majorkernelpanic\streaming\hw\EncoderDebugger.html
|
||||
* doc\net\majorkernelpanic\streaming\hw\NV21Convertor.html
|
||||
* doc\net\majorkernelpanic\streaming\hw\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\hw\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\hw\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\mp4\
|
||||
* doc\net\majorkernelpanic\streaming\mp4\MP4Config.html
|
||||
* doc\net\majorkernelpanic\streaming\mp4\MP4Parser.html
|
||||
* doc\net\majorkernelpanic\streaming\mp4\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\mp4\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\mp4\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\rtcp\
|
||||
* doc\net\majorkernelpanic\streaming\rtcp\SenderReport.html
|
||||
* doc\net\majorkernelpanic\streaming\rtcp\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\rtcp\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\rtcp\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\
|
||||
* doc\net\majorkernelpanic\streaming\rtp\AACADTSPacketizer.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\AACLATMPacketizer.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\AMRNBPacketizer.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\AbstractPacketizer.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\H263Packetizer.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\H264Packetizer.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\MediaCodecInputStream.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\RtpSocket.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\rtp\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\RtspClient.Callback.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\RtspClient.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\RtspServer.CallbackListener.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\RtspServer.LocalBinder.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\RtspServer.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\UriParser.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\rtsp\package-tree.html
|
||||
* doc\net\majorkernelpanic\streaming\video\
|
||||
* doc\net\majorkernelpanic\streaming\video\CodecManager.html
|
||||
* doc\net\majorkernelpanic\streaming\video\H263Stream.html
|
||||
* doc\net\majorkernelpanic\streaming\video\H264Stream.html
|
||||
* doc\net\majorkernelpanic\streaming\video\VideoQuality.html
|
||||
* doc\net\majorkernelpanic\streaming\video\VideoStream.html
|
||||
* doc\net\majorkernelpanic\streaming\video\package-frame.html
|
||||
* doc\net\majorkernelpanic\streaming\video\package-summary.html
|
||||
* doc\net\majorkernelpanic\streaming\video\package-tree.html
|
||||
* doc\overview-frame.html
|
||||
* doc\overview-summary.html
|
||||
* doc\overview-tree.html
|
||||
* doc\package-list
|
||||
* doc\resources\
|
||||
* doc\resources\background.gif
|
||||
* doc\resources\tab.gif
|
||||
* doc\resources\titlebar.gif
|
||||
* doc\resources\titlebar_end.gif
|
||||
* doc\serialized-form.html
|
||||
* doc\stylesheet.css
|
||||
* pom.xml
|
||||
* proguard-project.txt
|
||||
|
||||
Replaced Jars with Dependencies:
|
||||
--------------------------------
|
||||
The importer recognized the following .jar files as third party
|
||||
libraries and replaced them with Gradle dependencies instead. This has
|
||||
the advantage that more explicit version information is known, and the
|
||||
libraries can be updated automatically. However, it is possible that
|
||||
the .jar file in your project was of an older version than the
|
||||
dependency we picked, which could render the project not compileable.
|
||||
You can disable the jar replacement in the import wizard and try again:
|
||||
|
||||
android-support-v4.jar => com.android.support:support-v4:19.1.0
|
||||
android-support-v7-appcompat.jar => com.android.support:appcompat-v7:19.1.0
|
||||
gson-2.2.2_android.jar => com.google.code.gson:gson:2.3.1
|
||||
|
||||
Replaced Libraries with Dependencies:
|
||||
-------------------------------------
|
||||
The importer recognized the following library projects as third party
|
||||
libraries and replaced them with Gradle dependencies instead. This has
|
||||
the advantage that more explicit version information is known, and the
|
||||
libraries can be updated automatically. However, it is possible that
|
||||
the source files in your project were of an older version than the
|
||||
dependency we picked, which could render the project not compileable.
|
||||
You can disable the library replacement in the import wizard and try
|
||||
again:
|
||||
|
||||
android-support-v7-appcompat => [com.android.support:appcompat-v7:19.1.0]
|
||||
|
||||
Moved Files:
|
||||
------------
|
||||
Android Gradle projects use a different directory structure than ADT
|
||||
Eclipse projects. Here's how the projects were restructured:
|
||||
|
||||
In libstreaming:
|
||||
* AndroidManifest.xml => libstreaming\src\main\AndroidManifest.xml
|
||||
* assets\ => libstreaming\src\main\assets
|
||||
* libs\android-logging-log4j-1.0.3.jar => libstreaming\libs\android-logging-log4j-1.0.3.jar
|
||||
* libs\log4j-1.2.17.jar => libstreaming\libs\log4j-1.2.17.jar
|
||||
* res\ => libstreaming\src\main\res
|
||||
* src\ => libstreaming\src\main\java\
|
||||
In MediaUploader:
|
||||
* AndroidManifest.xml => mediaUploader\src\main\AndroidManifest.xml
|
||||
* assets\ => mediaUploader\src\main\assets
|
||||
* libs\armeabi\libUtils.so => mediaUploader\src\main\jniLibs\armeabi\libUtils.so
|
||||
* res\ => mediaUploader\src\main\res\
|
||||
* src\ => mediaUploader\src\main\java\
|
||||
|
||||
Next Steps:
|
||||
-----------
|
||||
You can now build the project. The Gradle project needs network
|
||||
connectivity to download dependencies.
|
||||
|
||||
Bugs:
|
||||
-----
|
||||
If for some reason your project does not build, and you determine that
|
||||
it is due to a bug or limitation of the Eclipse to Gradle importer,
|
||||
please file a bug at http://b.android.com with category
|
||||
Component-Tools.
|
||||
|
||||
(This import summary is for your information only, and can be deleted
|
||||
after import once you are satisfied with the results.)
|
||||
1
photoview/.gitignore
vendored
Normal file
1
photoview/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
36
photoview/build.gradle
Normal file
36
photoview/build.gradle
Normal file
@@ -0,0 +1,36 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.github.chrisbanes.photoview'
|
||||
compileSdk {
|
||||
version = release(36)
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdk 28
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation libs.androidx.appcompat
|
||||
implementation libs.material.components
|
||||
testImplementation libs.junit
|
||||
androidTestImplementation libs.androidx.junit
|
||||
androidTestImplementation libs.androidx.espresso.core
|
||||
}
|
||||
0
photoview/consumer-rules.pro
Normal file
0
photoview/consumer-rules.pro
Normal file
21
photoview/proguard-rules.pro
vendored
Normal file
21
photoview/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("com.github.chrisbanes.photoview.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
4
photoview/src/main/AndroidManifest.xml
Normal file
4
photoview/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2011, 2012 Chris Banes.
|
||||
|
||||
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.
|
||||
*/
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.view.View;
|
||||
|
||||
class Compat {
|
||||
|
||||
private static final int SIXTY_FPS_INTERVAL = 1000 / 60;
|
||||
|
||||
public static void postOnAnimation(View view, Runnable runnable) {
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
|
||||
postOnAnimationJellyBean(view, runnable);
|
||||
} else {
|
||||
view.postDelayed(runnable, SIXTY_FPS_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
private static void postOnAnimationJellyBean(View view, Runnable runnable) {
|
||||
view.postOnAnimation(runnable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
Copyright 2011, 2012 Chris Banes.
|
||||
<p/>
|
||||
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
|
||||
<p/>
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
<p/>
|
||||
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.
|
||||
*/
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
/**
|
||||
* Does a whole lot of gesture detecting.
|
||||
*/
|
||||
class CustomGestureDetector {
|
||||
|
||||
private static final int INVALID_POINTER_ID = -1;
|
||||
|
||||
private int mActivePointerId = INVALID_POINTER_ID;
|
||||
private int mActivePointerIndex = 0;
|
||||
private final ScaleGestureDetector mDetector;
|
||||
|
||||
private VelocityTracker mVelocityTracker;
|
||||
private boolean mIsDragging;
|
||||
private float mLastTouchX;
|
||||
private float mLastTouchY;
|
||||
private final float mTouchSlop;
|
||||
private final float mMinimumVelocity;
|
||||
private OnGestureListener mListener;
|
||||
|
||||
CustomGestureDetector(Context context, OnGestureListener listener) {
|
||||
final ViewConfiguration configuration = ViewConfiguration
|
||||
.get(context);
|
||||
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
|
||||
mTouchSlop = configuration.getScaledTouchSlop();
|
||||
|
||||
mListener = listener;
|
||||
ScaleGestureDetector.OnScaleGestureListener mScaleListener = new ScaleGestureDetector.OnScaleGestureListener() {
|
||||
private float lastFocusX, lastFocusY = 0;
|
||||
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float scaleFactor = detector.getScaleFactor();
|
||||
|
||||
if (Float.isNaN(scaleFactor) || Float.isInfinite(scaleFactor))
|
||||
return false;
|
||||
|
||||
if (scaleFactor >= 0) {
|
||||
mListener.onScale(scaleFactor,
|
||||
detector.getFocusX(),
|
||||
detector.getFocusY(),
|
||||
detector.getFocusX() - lastFocusX,
|
||||
detector.getFocusY() - lastFocusY
|
||||
);
|
||||
lastFocusX = detector.getFocusX();
|
||||
lastFocusY = detector.getFocusY();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
lastFocusX = detector.getFocusX();
|
||||
lastFocusY = detector.getFocusY();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
// NO-OP
|
||||
}
|
||||
};
|
||||
mDetector = new ScaleGestureDetector(context, mScaleListener);
|
||||
}
|
||||
|
||||
private float getActiveX(MotionEvent ev) {
|
||||
try {
|
||||
return ev.getX(mActivePointerIndex);
|
||||
} catch (Exception e) {
|
||||
return ev.getX();
|
||||
}
|
||||
}
|
||||
|
||||
private float getActiveY(MotionEvent ev) {
|
||||
try {
|
||||
return ev.getY(mActivePointerIndex);
|
||||
} catch (Exception e) {
|
||||
return ev.getY();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isScaling() {
|
||||
return mDetector.isInProgress();
|
||||
}
|
||||
|
||||
public boolean isDragging() {
|
||||
return mIsDragging;
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
mDetector.onTouchEvent(ev);
|
||||
return processTouchEvent(ev);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Fix for support lib bug, happening when onDestroy is called
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean processTouchEvent(MotionEvent ev) {
|
||||
final int action = ev.getAction();
|
||||
switch (action & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mActivePointerId = ev.getPointerId(0);
|
||||
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
if (null != mVelocityTracker) {
|
||||
mVelocityTracker.addMovement(ev);
|
||||
}
|
||||
|
||||
mLastTouchX = getActiveX(ev);
|
||||
mLastTouchY = getActiveY(ev);
|
||||
mIsDragging = false;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
final float x = getActiveX(ev);
|
||||
final float y = getActiveY(ev);
|
||||
final float dx = x - mLastTouchX, dy = y - mLastTouchY;
|
||||
|
||||
if (!mIsDragging) {
|
||||
// Use Pythagoras to see if drag length is larger than
|
||||
// touch slop
|
||||
mIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
|
||||
}
|
||||
|
||||
if (mIsDragging) {
|
||||
mListener.onDrag(dx, dy);
|
||||
mLastTouchX = x;
|
||||
mLastTouchY = y;
|
||||
|
||||
if (null != mVelocityTracker) {
|
||||
mVelocityTracker.addMovement(ev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mActivePointerId = INVALID_POINTER_ID;
|
||||
// Recycle Velocity Tracker
|
||||
if (null != mVelocityTracker) {
|
||||
mVelocityTracker.recycle();
|
||||
mVelocityTracker = null;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
mActivePointerId = INVALID_POINTER_ID;
|
||||
if (mIsDragging) {
|
||||
if (null != mVelocityTracker) {
|
||||
mLastTouchX = getActiveX(ev);
|
||||
mLastTouchY = getActiveY(ev);
|
||||
|
||||
// Compute velocity within the last 1000ms
|
||||
mVelocityTracker.addMovement(ev);
|
||||
mVelocityTracker.computeCurrentVelocity(1000);
|
||||
|
||||
final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker
|
||||
.getYVelocity();
|
||||
|
||||
// If the velocity is greater than minVelocity, call
|
||||
// listener
|
||||
if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
|
||||
mListener.onFling(mLastTouchX, mLastTouchY, -vX,
|
||||
-vY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recycle Velocity Tracker
|
||||
if (null != mVelocityTracker) {
|
||||
mVelocityTracker.recycle();
|
||||
mVelocityTracker = null;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
final int pointerIndex = Util.getPointerIndex(ev.getAction());
|
||||
final int pointerId = ev.getPointerId(pointerIndex);
|
||||
if (pointerId == mActivePointerId) {
|
||||
// This was our active pointer going up. Choose a new
|
||||
// active pointer and adjust accordingly.
|
||||
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
|
||||
mActivePointerId = ev.getPointerId(newPointerIndex);
|
||||
mLastTouchX = ev.getX(newPointerIndex);
|
||||
mLastTouchY = ev.getY(newPointerIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mActivePointerIndex = ev
|
||||
.findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId
|
||||
: 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2011, 2012 Chris Banes.
|
||||
|
||||
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.
|
||||
*/
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
interface OnGestureListener {
|
||||
|
||||
void onDrag(float dx, float dy);
|
||||
|
||||
void onFling(float startX, float startY, float velocityX,
|
||||
float velocityY);
|
||||
|
||||
void onScale(float scaleFactor, float focusX, float focusY);
|
||||
|
||||
void onScale(float scaleFactor, float focusX, float focusY, float dx, float dy);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the internal Matrix has changed for
|
||||
* this View.
|
||||
*/
|
||||
public interface OnMatrixChangedListener {
|
||||
|
||||
/**
|
||||
* Callback for when the Matrix displaying the Drawable has changed. This could be because
|
||||
* the View's bounds have changed, or the user has zoomed.
|
||||
*
|
||||
* @param rect - Rectangle displaying the Drawable's new bounds.
|
||||
*/
|
||||
void onMatrixChanged(RectF rect);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* Callback when the user tapped outside of the photo
|
||||
*/
|
||||
public interface OnOutsidePhotoTapListener {
|
||||
|
||||
/**
|
||||
* The outside of the photo has been tapped
|
||||
*/
|
||||
void onOutsidePhotoTap(ImageView imageView);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* A callback to be invoked when the Photo is tapped with a single
|
||||
* tap.
|
||||
*/
|
||||
public interface OnPhotoTapListener {
|
||||
|
||||
/**
|
||||
* A callback to receive where the user taps on a photo. You will only receive a callback if
|
||||
* the user taps on the actual photo, tapping on 'whitespace' will be ignored.
|
||||
*
|
||||
* @param view ImageView the user tapped.
|
||||
* @param x where the user tapped from the of the Drawable, as percentage of the
|
||||
* Drawable width.
|
||||
* @param y where the user tapped from the top of the Drawable, as percentage of the
|
||||
* Drawable height.
|
||||
*/
|
||||
void onPhotoTap(ImageView view, float x, float y);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
|
||||
/**
|
||||
* Interface definition for callback to be invoked when attached ImageView scale changes
|
||||
*/
|
||||
public interface OnScaleChangedListener {
|
||||
|
||||
/**
|
||||
* Callback for when the scale changes
|
||||
*
|
||||
* @param scaleFactor the scale factor (less than 1 for zoom out, greater than 1 for zoom in)
|
||||
* @param focusX focal point X position
|
||||
* @param focusY focal point Y position
|
||||
*/
|
||||
void onScaleChange(float scaleFactor, float focusX, float focusY);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* A callback to be invoked when the ImageView is flung with a single
|
||||
* touch
|
||||
*/
|
||||
public interface OnSingleFlingListener {
|
||||
|
||||
/**
|
||||
* A callback to receive where the user flings on a ImageView. You will receive a callback if
|
||||
* the user flings anywhere on the view.
|
||||
*
|
||||
* @param e1 MotionEvent the user first touch.
|
||||
* @param e2 MotionEvent the user last touch.
|
||||
* @param velocityX distance of user's horizontal fling.
|
||||
* @param velocityY distance of user's vertical fling.
|
||||
*/
|
||||
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the photo is experiencing a drag event
|
||||
*/
|
||||
public interface OnViewDragListener {
|
||||
|
||||
/**
|
||||
* Callback for when the photo is experiencing a drag event. This cannot be invoked when the
|
||||
* user is scaling.
|
||||
*
|
||||
* @param dx The change of the coordinates in the x-direction
|
||||
* @param dy The change of the coordinates in the y-direction
|
||||
*/
|
||||
void onDrag(float dx, float dy);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
public interface OnViewTapListener {
|
||||
|
||||
/**
|
||||
* A callback to receive where the user taps on a ImageView. You will receive a callback if
|
||||
* the user taps anywhere on the view, tapping on 'whitespace' will not be ignored.
|
||||
*
|
||||
* @param view - View the user tapped.
|
||||
* @param x - where the user tapped from the left of the View.
|
||||
* @param y - where the user tapped from the top of the View.
|
||||
*/
|
||||
void onViewTap(View view, float x, float y);
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
Copyright 2011, 2012 Chris Banes.
|
||||
<p>
|
||||
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
|
||||
<p>
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
<p>
|
||||
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.
|
||||
*/
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.GestureDetector;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
/**
|
||||
* A zoomable ImageView. See {@link PhotoViewAttacher} for most of the details on how the zooming
|
||||
* is accomplished
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PhotoView extends AppCompatImageView {
|
||||
|
||||
private PhotoViewAttacher attacher;
|
||||
private ScaleType pendingScaleType;
|
||||
|
||||
public PhotoView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public PhotoView(Context context, AttributeSet attr) {
|
||||
this(context, attr, 0);
|
||||
}
|
||||
|
||||
public PhotoView(Context context, AttributeSet attr, int defStyle) {
|
||||
super(context, attr, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
attacher = new PhotoViewAttacher(this);
|
||||
//We always pose as a Matrix scale type, though we can change to another scale type
|
||||
//via the attacher
|
||||
super.setScaleType(ScaleType.MATRIX);
|
||||
//apply the previously applied scale type
|
||||
if (pendingScaleType != null) {
|
||||
setScaleType(pendingScaleType);
|
||||
pendingScaleType = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current {@link PhotoViewAttacher} for this view. Be wary of holding on to references
|
||||
* to this attacher, as it has a reference to this view, which, if a reference is held in the
|
||||
* wrong place, can cause memory leaks.
|
||||
*
|
||||
* @return the attacher.
|
||||
*/
|
||||
public PhotoViewAttacher getAttacher() {
|
||||
return attacher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScaleType getScaleType() {
|
||||
return attacher.getScaleType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix getImageMatrix() {
|
||||
return attacher.getImageMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnLongClickListener(OnLongClickListener l) {
|
||||
attacher.setOnLongClickListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnClickListener(OnClickListener l) {
|
||||
attacher.setOnClickListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScaleType(ScaleType scaleType) {
|
||||
if (attacher == null) {
|
||||
pendingScaleType = scaleType;
|
||||
} else {
|
||||
attacher.setScaleType(scaleType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageDrawable(Drawable drawable) {
|
||||
super.setImageDrawable(drawable);
|
||||
// setImageBitmap calls through to this method
|
||||
if (attacher != null) {
|
||||
attacher.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageResource(int resId) {
|
||||
super.setImageResource(resId);
|
||||
if (attacher != null) {
|
||||
attacher.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageURI(Uri uri) {
|
||||
super.setImageURI(uri);
|
||||
if (attacher != null) {
|
||||
attacher.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setFrame(int l, int t, int r, int b) {
|
||||
boolean changed = super.setFrame(l, t, r, b);
|
||||
if (changed) {
|
||||
attacher.update();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public void setRotationTo(float rotationDegree) {
|
||||
attacher.setRotationTo(rotationDegree);
|
||||
}
|
||||
|
||||
public void setRotationBy(float rotationDegree) {
|
||||
attacher.setRotationBy(rotationDegree);
|
||||
}
|
||||
|
||||
public boolean isZoomable() {
|
||||
return attacher.isZoomable();
|
||||
}
|
||||
|
||||
public void setZoomable(boolean zoomable) {
|
||||
attacher.setZoomable(zoomable);
|
||||
}
|
||||
|
||||
public RectF getDisplayRect() {
|
||||
return attacher.getDisplayRect();
|
||||
}
|
||||
|
||||
public void getDisplayMatrix(Matrix matrix) {
|
||||
attacher.getDisplayMatrix(matrix);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue") public boolean setDisplayMatrix(Matrix finalRectangle) {
|
||||
return attacher.setDisplayMatrix(finalRectangle);
|
||||
}
|
||||
|
||||
public void getSuppMatrix(Matrix matrix) {
|
||||
attacher.getSuppMatrix(matrix);
|
||||
}
|
||||
|
||||
public boolean setSuppMatrix(Matrix matrix) {
|
||||
return attacher.setDisplayMatrix(matrix);
|
||||
}
|
||||
|
||||
public float getMinimumScale() {
|
||||
return attacher.getMinimumScale();
|
||||
}
|
||||
|
||||
public float getMediumScale() {
|
||||
return attacher.getMediumScale();
|
||||
}
|
||||
|
||||
public float getMaximumScale() {
|
||||
return attacher.getMaximumScale();
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return attacher.getScale();
|
||||
}
|
||||
|
||||
public void setAllowParentInterceptOnEdge(boolean allow) {
|
||||
attacher.setAllowParentInterceptOnEdge(allow);
|
||||
}
|
||||
|
||||
public void setMinimumScale(float minimumScale) {
|
||||
attacher.setMinimumScale(minimumScale);
|
||||
}
|
||||
|
||||
public void setMediumScale(float mediumScale) {
|
||||
attacher.setMediumScale(mediumScale);
|
||||
}
|
||||
|
||||
public void setMaximumScale(float maximumScale) {
|
||||
attacher.setMaximumScale(maximumScale);
|
||||
}
|
||||
|
||||
public void setScaleLevels(float minimumScale, float mediumScale, float maximumScale) {
|
||||
attacher.setScaleLevels(minimumScale, mediumScale, maximumScale);
|
||||
}
|
||||
|
||||
public void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
|
||||
attacher.setOnMatrixChangeListener(listener);
|
||||
}
|
||||
|
||||
public void setOnPhotoTapListener(OnPhotoTapListener listener) {
|
||||
attacher.setOnPhotoTapListener(listener);
|
||||
}
|
||||
|
||||
public void setOnOutsidePhotoTapListener(OnOutsidePhotoTapListener listener) {
|
||||
attacher.setOnOutsidePhotoTapListener(listener);
|
||||
}
|
||||
|
||||
public void setOnViewTapListener(OnViewTapListener listener) {
|
||||
attacher.setOnViewTapListener(listener);
|
||||
}
|
||||
|
||||
public void setOnViewDragListener(OnViewDragListener listener) {
|
||||
attacher.setOnViewDragListener(listener);
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
attacher.setScale(scale);
|
||||
}
|
||||
|
||||
public void setScale(float scale, boolean animate) {
|
||||
attacher.setScale(scale, animate);
|
||||
}
|
||||
|
||||
public void setScale(float scale, float focalX, float focalY, boolean animate) {
|
||||
attacher.setScale(scale, focalX, focalY, animate);
|
||||
}
|
||||
|
||||
public void setZoomTransitionDuration(int milliseconds) {
|
||||
attacher.setZoomTransitionDuration(milliseconds);
|
||||
}
|
||||
|
||||
public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) {
|
||||
attacher.setOnDoubleTapListener(onDoubleTapListener);
|
||||
}
|
||||
|
||||
public void setOnScaleChangeListener(OnScaleChangedListener onScaleChangedListener) {
|
||||
attacher.setOnScaleChangeListener(onScaleChangedListener);
|
||||
}
|
||||
|
||||
public void setOnSingleFlingListener(OnSingleFlingListener onSingleFlingListener) {
|
||||
attacher.setOnSingleFlingListener(onSingleFlingListener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,823 @@
|
||||
/*
|
||||
Copyright 2011, 2012 Chris Banes.
|
||||
<p>
|
||||
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
|
||||
<p>
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
<p>
|
||||
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.
|
||||
*/
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Matrix.ScaleToFit;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.view.ViewParent;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ImageView.ScaleType;
|
||||
import android.widget.OverScroller;
|
||||
|
||||
/**
|
||||
* The component of {@link PhotoView} which does the work allowing for zooming, scaling, panning, etc.
|
||||
* It is made public in case you need to subclass something other than AppCompatImageView and still
|
||||
* gain the functionality that {@link PhotoView} offers
|
||||
*/
|
||||
public class PhotoViewAttacher implements View.OnTouchListener,
|
||||
View.OnLayoutChangeListener {
|
||||
|
||||
private static float DEFAULT_MAX_SCALE = 3.0f;
|
||||
private static float DEFAULT_MID_SCALE = 1.75f;
|
||||
private static float DEFAULT_MIN_SCALE = 1.0f;
|
||||
private static int DEFAULT_ZOOM_DURATION = 200;
|
||||
|
||||
private static final int HORIZONTAL_EDGE_NONE = -1;
|
||||
private static final int HORIZONTAL_EDGE_LEFT = 0;
|
||||
private static final int HORIZONTAL_EDGE_RIGHT = 1;
|
||||
private static final int HORIZONTAL_EDGE_BOTH = 2;
|
||||
private static final int VERTICAL_EDGE_NONE = -1;
|
||||
private static final int VERTICAL_EDGE_TOP = 0;
|
||||
private static final int VERTICAL_EDGE_BOTTOM = 1;
|
||||
private static final int VERTICAL_EDGE_BOTH = 2;
|
||||
private static int SINGLE_TOUCH = 1;
|
||||
|
||||
private Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
|
||||
private int mZoomDuration = DEFAULT_ZOOM_DURATION;
|
||||
private float mMinScale = DEFAULT_MIN_SCALE;
|
||||
private float mMidScale = DEFAULT_MID_SCALE;
|
||||
private float mMaxScale = DEFAULT_MAX_SCALE;
|
||||
|
||||
private boolean mAllowParentInterceptOnEdge = true;
|
||||
private boolean mBlockParentIntercept = false;
|
||||
|
||||
private ImageView mImageView;
|
||||
|
||||
// Gesture Detectors
|
||||
private GestureDetector mGestureDetector;
|
||||
private CustomGestureDetector mScaleDragDetector;
|
||||
|
||||
// These are set so we don't keep allocating them on the heap
|
||||
private final Matrix mBaseMatrix = new Matrix();
|
||||
private final Matrix mDrawMatrix = new Matrix();
|
||||
private final Matrix mSuppMatrix = new Matrix();
|
||||
private final RectF mDisplayRect = new RectF();
|
||||
private final float[] mMatrixValues = new float[9];
|
||||
|
||||
// Listeners
|
||||
private OnMatrixChangedListener mMatrixChangeListener;
|
||||
private OnPhotoTapListener mPhotoTapListener;
|
||||
private OnOutsidePhotoTapListener mOutsidePhotoTapListener;
|
||||
private OnViewTapListener mViewTapListener;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
private OnLongClickListener mLongClickListener;
|
||||
private OnScaleChangedListener mScaleChangeListener;
|
||||
private OnSingleFlingListener mSingleFlingListener;
|
||||
private OnViewDragListener mOnViewDragListener;
|
||||
|
||||
private FlingRunnable mCurrentFlingRunnable;
|
||||
private int mHorizontalScrollEdge = HORIZONTAL_EDGE_BOTH;
|
||||
private int mVerticalScrollEdge = VERTICAL_EDGE_BOTH;
|
||||
private float mBaseRotation;
|
||||
|
||||
private boolean mZoomEnabled = true;
|
||||
private ScaleType mScaleType = ScaleType.FIT_CENTER;
|
||||
|
||||
private OnGestureListener onGestureListener = new OnGestureListener() {
|
||||
@Override
|
||||
public void onDrag(float dx, float dy) {
|
||||
if (mScaleDragDetector.isScaling()) {
|
||||
return; // Do not drag if we are already scaling
|
||||
}
|
||||
if (mOnViewDragListener != null) {
|
||||
mOnViewDragListener.onDrag(dx, dy);
|
||||
}
|
||||
mSuppMatrix.postTranslate(dx, dy);
|
||||
checkAndDisplayMatrix();
|
||||
|
||||
/*
|
||||
* Here we decide whether to let the ImageView's parent to start taking
|
||||
* over the touch event.
|
||||
*
|
||||
* First we check whether this function is enabled. We never want the
|
||||
* parent to take over if we're scaling. We then check the edge we're
|
||||
* on, and the direction of the scroll (i.e. if we're pulling against
|
||||
* the edge, aka 'overscrolling', let the parent take over).
|
||||
*/
|
||||
ViewParent parent = mImageView.getParent();
|
||||
if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling() && !mBlockParentIntercept) {
|
||||
if (mHorizontalScrollEdge == HORIZONTAL_EDGE_BOTH
|
||||
|| (mHorizontalScrollEdge == HORIZONTAL_EDGE_LEFT && dx >= 1f)
|
||||
|| (mHorizontalScrollEdge == HORIZONTAL_EDGE_RIGHT && dx <= -1f)
|
||||
|| (mVerticalScrollEdge == VERTICAL_EDGE_TOP && dy >= 1f)
|
||||
|| (mVerticalScrollEdge == VERTICAL_EDGE_BOTTOM && dy <= -1f)) {
|
||||
if (parent != null) {
|
||||
parent.requestDisallowInterceptTouchEvent(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (parent != null) {
|
||||
parent.requestDisallowInterceptTouchEvent(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFling(float startX, float startY, float velocityX, float velocityY) {
|
||||
mCurrentFlingRunnable = new FlingRunnable(mImageView.getContext());
|
||||
mCurrentFlingRunnable.fling(getImageViewWidth(mImageView),
|
||||
getImageViewHeight(mImageView), (int) velocityX, (int) velocityY);
|
||||
mImageView.post(mCurrentFlingRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScale(float scaleFactor, float focusX, float focusY) {
|
||||
onScale(scaleFactor, focusX, focusY, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScale(float scaleFactor, float focusX, float focusY, float dx, float dy) {
|
||||
if (getScale() < mMaxScale || scaleFactor < 1f) {
|
||||
if (mScaleChangeListener != null) {
|
||||
mScaleChangeListener.onScaleChange(scaleFactor, focusX, focusY);
|
||||
}
|
||||
mSuppMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY);
|
||||
mSuppMatrix.postTranslate(dx, dy);
|
||||
checkAndDisplayMatrix();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public PhotoViewAttacher(ImageView imageView) {
|
||||
mImageView = imageView;
|
||||
imageView.setOnTouchListener(this);
|
||||
imageView.addOnLayoutChangeListener(this);
|
||||
if (imageView.isInEditMode()) {
|
||||
return;
|
||||
}
|
||||
mBaseRotation = 0.0f;
|
||||
// Create Gesture Detectors...
|
||||
mScaleDragDetector = new CustomGestureDetector(imageView.getContext(), onGestureListener);
|
||||
mGestureDetector = new GestureDetector(imageView.getContext(), new GestureDetector.SimpleOnGestureListener() {
|
||||
|
||||
// forward long click listener
|
||||
@Override
|
||||
public void onLongPress(MotionEvent e) {
|
||||
if (mLongClickListener != null) {
|
||||
mLongClickListener.onLongClick(mImageView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2,
|
||||
float velocityX, float velocityY) {
|
||||
if (mSingleFlingListener != null) {
|
||||
if (getScale() > DEFAULT_MIN_SCALE) {
|
||||
return false;
|
||||
}
|
||||
if (e1.getPointerCount() > SINGLE_TOUCH
|
||||
|| e2.getPointerCount() > SINGLE_TOUCH) {
|
||||
return false;
|
||||
}
|
||||
return mSingleFlingListener.onFling(e1, e2, velocityX, velocityY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
if (mOnClickListener != null) {
|
||||
mOnClickListener.onClick(mImageView);
|
||||
}
|
||||
final RectF displayRect = getDisplayRect();
|
||||
final float x = e.getX(), y = e.getY();
|
||||
if (mViewTapListener != null) {
|
||||
mViewTapListener.onViewTap(mImageView, x, y);
|
||||
}
|
||||
if (displayRect != null) {
|
||||
// Check to see if the user tapped on the photo
|
||||
if (displayRect.contains(x, y)) {
|
||||
float xResult = (x - displayRect.left)
|
||||
/ displayRect.width();
|
||||
float yResult = (y - displayRect.top)
|
||||
/ displayRect.height();
|
||||
if (mPhotoTapListener != null) {
|
||||
mPhotoTapListener.onPhotoTap(mImageView, xResult, yResult);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (mOutsidePhotoTapListener != null) {
|
||||
mOutsidePhotoTapListener.onOutsidePhotoTap(mImageView);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent ev) {
|
||||
try {
|
||||
float scale = getScale();
|
||||
float x = ev.getX();
|
||||
float y = ev.getY();
|
||||
if (scale < getMediumScale()) {
|
||||
setScale(getMediumScale(), x, y, true);
|
||||
} else if (scale >= getMediumScale() && scale < getMaximumScale()) {
|
||||
setScale(getMaximumScale(), x, y, true);
|
||||
} else {
|
||||
setScale(getMinimumScale(), x, y, true);
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
// Can sometimes happen when getX() and getY() is called
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTapEvent(MotionEvent e) {
|
||||
// Wait for the confirmed onDoubleTap() instead
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener) {
|
||||
this.mGestureDetector.setOnDoubleTapListener(newOnDoubleTapListener);
|
||||
}
|
||||
|
||||
public void setOnScaleChangeListener(OnScaleChangedListener onScaleChangeListener) {
|
||||
this.mScaleChangeListener = onScaleChangeListener;
|
||||
}
|
||||
|
||||
public void setOnSingleFlingListener(OnSingleFlingListener onSingleFlingListener) {
|
||||
this.mSingleFlingListener = onSingleFlingListener;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean isZoomEnabled() {
|
||||
return mZoomEnabled;
|
||||
}
|
||||
|
||||
public RectF getDisplayRect() {
|
||||
checkMatrixBounds();
|
||||
return getDisplayRect(getDrawMatrix());
|
||||
}
|
||||
|
||||
public boolean setDisplayMatrix(Matrix finalMatrix) {
|
||||
if (finalMatrix == null) {
|
||||
throw new IllegalArgumentException("Matrix cannot be null");
|
||||
}
|
||||
if (mImageView.getDrawable() == null) {
|
||||
return false;
|
||||
}
|
||||
mSuppMatrix.set(finalMatrix);
|
||||
checkAndDisplayMatrix();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setBaseRotation(final float degrees) {
|
||||
mBaseRotation = degrees % 360;
|
||||
update();
|
||||
setRotationBy(mBaseRotation);
|
||||
checkAndDisplayMatrix();
|
||||
}
|
||||
|
||||
public void setRotationTo(float degrees) {
|
||||
mSuppMatrix.setRotate(degrees % 360);
|
||||
checkAndDisplayMatrix();
|
||||
}
|
||||
|
||||
public void setRotationBy(float degrees) {
|
||||
mSuppMatrix.postRotate(degrees % 360);
|
||||
checkAndDisplayMatrix();
|
||||
}
|
||||
|
||||
public float getMinimumScale() {
|
||||
return mMinScale;
|
||||
}
|
||||
|
||||
public float getMediumScale() {
|
||||
return mMidScale;
|
||||
}
|
||||
|
||||
public float getMaximumScale() {
|
||||
return mMaxScale;
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return (float) Math.sqrt((float) Math.pow(getValue(mSuppMatrix, Matrix.MSCALE_X), 2) + (float) Math.pow
|
||||
(getValue(mSuppMatrix, Matrix.MSKEW_Y), 2));
|
||||
}
|
||||
|
||||
public ScaleType getScaleType() {
|
||||
return mScaleType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int
|
||||
oldRight, int oldBottom) {
|
||||
// Update our base matrix, as the bounds have changed
|
||||
if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) {
|
||||
updateBaseMatrix(mImageView.getDrawable());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent ev) {
|
||||
boolean handled = false;
|
||||
if (mZoomEnabled && Util.hasDrawable((ImageView) v)) {
|
||||
switch (ev.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
ViewParent parent = v.getParent();
|
||||
// First, disable the Parent from intercepting the touch
|
||||
// event
|
||||
if (parent != null) {
|
||||
parent.requestDisallowInterceptTouchEvent(true);
|
||||
}
|
||||
// If we're flinging, and the user presses down, cancel
|
||||
// fling
|
||||
cancelFling();
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
// If the user has zoomed less than min scale, zoom back
|
||||
// to min scale
|
||||
if (getScale() < mMinScale) {
|
||||
RectF rect = getDisplayRect();
|
||||
if (rect != null) {
|
||||
v.post(new AnimatedZoomRunnable(getScale(), mMinScale,
|
||||
rect.centerX(), rect.centerY()));
|
||||
handled = true;
|
||||
}
|
||||
} else if (getScale() > mMaxScale) {
|
||||
RectF rect = getDisplayRect();
|
||||
if (rect != null) {
|
||||
v.post(new AnimatedZoomRunnable(getScale(), mMaxScale,
|
||||
rect.centerX(), rect.centerY()));
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Try the Scale/Drag detector
|
||||
if (mScaleDragDetector != null) {
|
||||
boolean wasScaling = mScaleDragDetector.isScaling();
|
||||
boolean wasDragging = mScaleDragDetector.isDragging();
|
||||
handled = mScaleDragDetector.onTouchEvent(ev);
|
||||
boolean didntScale = !wasScaling && !mScaleDragDetector.isScaling();
|
||||
boolean didntDrag = !wasDragging && !mScaleDragDetector.isDragging();
|
||||
mBlockParentIntercept = didntScale && didntDrag;
|
||||
}
|
||||
// Check to see if the user double tapped
|
||||
if (mGestureDetector != null && mGestureDetector.onTouchEvent(ev)) {
|
||||
handled = true;
|
||||
}
|
||||
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
public void setAllowParentInterceptOnEdge(boolean allow) {
|
||||
mAllowParentInterceptOnEdge = allow;
|
||||
}
|
||||
|
||||
public void setMinimumScale(float minimumScale) {
|
||||
Util.checkZoomLevels(minimumScale, mMidScale, mMaxScale);
|
||||
mMinScale = minimumScale;
|
||||
}
|
||||
|
||||
public void setMediumScale(float mediumScale) {
|
||||
Util.checkZoomLevels(mMinScale, mediumScale, mMaxScale);
|
||||
mMidScale = mediumScale;
|
||||
}
|
||||
|
||||
public void setMaximumScale(float maximumScale) {
|
||||
Util.checkZoomLevels(mMinScale, mMidScale, maximumScale);
|
||||
mMaxScale = maximumScale;
|
||||
}
|
||||
|
||||
public void setScaleLevels(float minimumScale, float mediumScale, float maximumScale) {
|
||||
Util.checkZoomLevels(minimumScale, mediumScale, maximumScale);
|
||||
mMinScale = minimumScale;
|
||||
mMidScale = mediumScale;
|
||||
mMaxScale = maximumScale;
|
||||
}
|
||||
|
||||
public void setOnLongClickListener(OnLongClickListener listener) {
|
||||
mLongClickListener = listener;
|
||||
}
|
||||
|
||||
public void setOnClickListener(View.OnClickListener listener) {
|
||||
mOnClickListener = listener;
|
||||
}
|
||||
|
||||
public void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
|
||||
mMatrixChangeListener = listener;
|
||||
}
|
||||
|
||||
public void setOnPhotoTapListener(OnPhotoTapListener listener) {
|
||||
mPhotoTapListener = listener;
|
||||
}
|
||||
|
||||
public void setOnOutsidePhotoTapListener(OnOutsidePhotoTapListener mOutsidePhotoTapListener) {
|
||||
this.mOutsidePhotoTapListener = mOutsidePhotoTapListener;
|
||||
}
|
||||
|
||||
public void setOnViewTapListener(OnViewTapListener listener) {
|
||||
mViewTapListener = listener;
|
||||
}
|
||||
|
||||
public void setOnViewDragListener(OnViewDragListener listener) {
|
||||
mOnViewDragListener = listener;
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
setScale(scale, false);
|
||||
}
|
||||
|
||||
public void setScale(float scale, boolean animate) {
|
||||
setScale(scale,
|
||||
(mImageView.getRight()) / 2,
|
||||
(mImageView.getBottom()) / 2,
|
||||
animate);
|
||||
}
|
||||
|
||||
public void setScale(float scale, float focalX, float focalY,
|
||||
boolean animate) {
|
||||
// Check to see if the scale is within bounds
|
||||
if (scale < mMinScale || scale > mMaxScale) {
|
||||
throw new IllegalArgumentException("Scale must be within the range of minScale and maxScale");
|
||||
}
|
||||
if (animate) {
|
||||
mImageView.post(new AnimatedZoomRunnable(getScale(), scale,
|
||||
focalX, focalY));
|
||||
} else {
|
||||
mSuppMatrix.setScale(scale, scale, focalX, focalY);
|
||||
checkAndDisplayMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the zoom interpolator
|
||||
*
|
||||
* @param interpolator the zoom interpolator
|
||||
*/
|
||||
public void setZoomInterpolator(Interpolator interpolator) {
|
||||
mInterpolator = interpolator;
|
||||
}
|
||||
|
||||
public void setScaleType(ScaleType scaleType) {
|
||||
if (Util.isSupportedScaleType(scaleType) && scaleType != mScaleType) {
|
||||
mScaleType = scaleType;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isZoomable() {
|
||||
return mZoomEnabled;
|
||||
}
|
||||
|
||||
public void setZoomable(boolean zoomable) {
|
||||
mZoomEnabled = zoomable;
|
||||
update();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (mZoomEnabled) {
|
||||
// Update the base matrix using the current drawable
|
||||
updateBaseMatrix(mImageView.getDrawable());
|
||||
} else {
|
||||
// Reset the Matrix...
|
||||
resetMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display matrix
|
||||
*
|
||||
* @param matrix target matrix to copy to
|
||||
*/
|
||||
public void getDisplayMatrix(Matrix matrix) {
|
||||
matrix.set(getDrawMatrix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current support matrix
|
||||
*/
|
||||
public void getSuppMatrix(Matrix matrix) {
|
||||
matrix.set(mSuppMatrix);
|
||||
}
|
||||
|
||||
private Matrix getDrawMatrix() {
|
||||
mDrawMatrix.set(mBaseMatrix);
|
||||
mDrawMatrix.postConcat(mSuppMatrix);
|
||||
return mDrawMatrix;
|
||||
}
|
||||
|
||||
public Matrix getImageMatrix() {
|
||||
return mDrawMatrix;
|
||||
}
|
||||
|
||||
public void setZoomTransitionDuration(int milliseconds) {
|
||||
this.mZoomDuration = milliseconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that 'unpacks' a Matrix and returns the required value
|
||||
*
|
||||
* @param matrix Matrix to unpack
|
||||
* @param whichValue Which value from Matrix.M* to return
|
||||
* @return returned value
|
||||
*/
|
||||
private float getValue(Matrix matrix, int whichValue) {
|
||||
matrix.getValues(mMatrixValues);
|
||||
return mMatrixValues[whichValue];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the Matrix back to FIT_CENTER, and then displays its contents
|
||||
*/
|
||||
private void resetMatrix() {
|
||||
mSuppMatrix.reset();
|
||||
setRotationBy(mBaseRotation);
|
||||
setImageViewMatrix(getDrawMatrix());
|
||||
checkMatrixBounds();
|
||||
}
|
||||
|
||||
private void setImageViewMatrix(Matrix matrix) {
|
||||
mImageView.setImageMatrix(matrix);
|
||||
// Call MatrixChangedListener if needed
|
||||
if (mMatrixChangeListener != null) {
|
||||
RectF displayRect = getDisplayRect(matrix);
|
||||
if (displayRect != null) {
|
||||
mMatrixChangeListener.onMatrixChanged(displayRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that simply checks the Matrix, and then displays the result
|
||||
*/
|
||||
private void checkAndDisplayMatrix() {
|
||||
if (checkMatrixBounds()) {
|
||||
setImageViewMatrix(getDrawMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that maps the supplied Matrix to the current Drawable
|
||||
*
|
||||
* @param matrix - Matrix to map Drawable against
|
||||
* @return RectF - Displayed Rectangle
|
||||
*/
|
||||
private RectF getDisplayRect(Matrix matrix) {
|
||||
Drawable d = mImageView.getDrawable();
|
||||
if (d != null) {
|
||||
mDisplayRect.set(0, 0, d.getIntrinsicWidth(),
|
||||
d.getIntrinsicHeight());
|
||||
matrix.mapRect(mDisplayRect);
|
||||
return mDisplayRect;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Matrix for FIT_CENTER
|
||||
*
|
||||
* @param drawable - Drawable being displayed
|
||||
*/
|
||||
private void updateBaseMatrix(Drawable drawable) {
|
||||
if (drawable == null) {
|
||||
return;
|
||||
}
|
||||
final float viewWidth = getImageViewWidth(mImageView);
|
||||
final float viewHeight = getImageViewHeight(mImageView);
|
||||
final int drawableWidth = drawable.getIntrinsicWidth();
|
||||
final int drawableHeight = drawable.getIntrinsicHeight();
|
||||
mBaseMatrix.reset();
|
||||
final float widthScale = viewWidth / drawableWidth;
|
||||
final float heightScale = viewHeight / drawableHeight;
|
||||
if (mScaleType == ScaleType.CENTER) {
|
||||
mBaseMatrix.postTranslate((viewWidth - drawableWidth) / 2F,
|
||||
(viewHeight - drawableHeight) / 2F);
|
||||
|
||||
} else if (mScaleType == ScaleType.CENTER_CROP) {
|
||||
float scale = Math.max(widthScale, heightScale);
|
||||
mBaseMatrix.postScale(scale, scale);
|
||||
mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
|
||||
(viewHeight - drawableHeight * scale) / 2F);
|
||||
|
||||
} else if (mScaleType == ScaleType.CENTER_INSIDE) {
|
||||
float scale = Math.min(1.0f, Math.min(widthScale, heightScale));
|
||||
mBaseMatrix.postScale(scale, scale);
|
||||
mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
|
||||
(viewHeight - drawableHeight * scale) / 2F);
|
||||
|
||||
} else {
|
||||
RectF mTempSrc = new RectF(0, 0, drawableWidth, drawableHeight);
|
||||
RectF mTempDst = new RectF(0, 0, viewWidth, viewHeight);
|
||||
if ((int) mBaseRotation % 180 != 0) {
|
||||
mTempSrc = new RectF(0, 0, drawableHeight, drawableWidth);
|
||||
}
|
||||
switch (mScaleType) {
|
||||
case FIT_CENTER:
|
||||
mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.CENTER);
|
||||
break;
|
||||
case FIT_START:
|
||||
mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.START);
|
||||
break;
|
||||
case FIT_END:
|
||||
mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.END);
|
||||
break;
|
||||
case FIT_XY:
|
||||
mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.FILL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
resetMatrix();
|
||||
}
|
||||
|
||||
private boolean checkMatrixBounds() {
|
||||
final RectF rect = getDisplayRect(getDrawMatrix());
|
||||
if (rect == null) {
|
||||
return false;
|
||||
}
|
||||
final float height = rect.height(), width = rect.width();
|
||||
float deltaX = 0, deltaY = 0;
|
||||
final int viewHeight = getImageViewHeight(mImageView);
|
||||
if (height <= viewHeight) {
|
||||
switch (mScaleType) {
|
||||
case FIT_START:
|
||||
deltaY = -rect.top;
|
||||
break;
|
||||
case FIT_END:
|
||||
deltaY = viewHeight - height - rect.top;
|
||||
break;
|
||||
default:
|
||||
deltaY = (viewHeight - height) / 2 - rect.top;
|
||||
break;
|
||||
}
|
||||
mVerticalScrollEdge = VERTICAL_EDGE_BOTH;
|
||||
} else if (rect.top > 0) {
|
||||
mVerticalScrollEdge = VERTICAL_EDGE_TOP;
|
||||
deltaY = -rect.top;
|
||||
} else if (rect.bottom < viewHeight) {
|
||||
mVerticalScrollEdge = VERTICAL_EDGE_BOTTOM;
|
||||
deltaY = viewHeight - rect.bottom;
|
||||
} else {
|
||||
mVerticalScrollEdge = VERTICAL_EDGE_NONE;
|
||||
}
|
||||
final int viewWidth = getImageViewWidth(mImageView);
|
||||
if (width <= viewWidth) {
|
||||
switch (mScaleType) {
|
||||
case FIT_START:
|
||||
deltaX = -rect.left;
|
||||
break;
|
||||
case FIT_END:
|
||||
deltaX = viewWidth - width - rect.left;
|
||||
break;
|
||||
default:
|
||||
deltaX = (viewWidth - width) / 2 - rect.left;
|
||||
break;
|
||||
}
|
||||
mHorizontalScrollEdge = HORIZONTAL_EDGE_BOTH;
|
||||
} else if (rect.left > 0) {
|
||||
mHorizontalScrollEdge = HORIZONTAL_EDGE_LEFT;
|
||||
deltaX = -rect.left;
|
||||
} else if (rect.right < viewWidth) {
|
||||
deltaX = viewWidth - rect.right;
|
||||
mHorizontalScrollEdge = HORIZONTAL_EDGE_RIGHT;
|
||||
} else {
|
||||
mHorizontalScrollEdge = HORIZONTAL_EDGE_NONE;
|
||||
}
|
||||
// Finally actually translate the matrix
|
||||
mSuppMatrix.postTranslate(deltaX, deltaY);
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getImageViewWidth(ImageView imageView) {
|
||||
return imageView.getWidth() - imageView.getPaddingLeft() - imageView.getPaddingRight();
|
||||
}
|
||||
|
||||
private int getImageViewHeight(ImageView imageView) {
|
||||
return imageView.getHeight() - imageView.getPaddingTop() - imageView.getPaddingBottom();
|
||||
}
|
||||
|
||||
private void cancelFling() {
|
||||
if (mCurrentFlingRunnable != null) {
|
||||
mCurrentFlingRunnable.cancelFling();
|
||||
mCurrentFlingRunnable = null;
|
||||
}
|
||||
}
|
||||
|
||||
private class AnimatedZoomRunnable implements Runnable {
|
||||
|
||||
private final float mFocalX, mFocalY;
|
||||
private final long mStartTime;
|
||||
private final float mZoomStart, mZoomEnd;
|
||||
|
||||
public AnimatedZoomRunnable(final float currentZoom, final float targetZoom,
|
||||
final float focalX, final float focalY) {
|
||||
mFocalX = focalX;
|
||||
mFocalY = focalY;
|
||||
mStartTime = System.currentTimeMillis();
|
||||
mZoomStart = currentZoom;
|
||||
mZoomEnd = targetZoom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
float t = interpolate();
|
||||
float scale = mZoomStart + t * (mZoomEnd - mZoomStart);
|
||||
float deltaScale = scale / getScale();
|
||||
onGestureListener.onScale(deltaScale, mFocalX, mFocalY);
|
||||
// We haven't hit our target scale yet, so post ourselves again
|
||||
if (t < 1f) {
|
||||
Compat.postOnAnimation(mImageView, this);
|
||||
}
|
||||
}
|
||||
|
||||
private float interpolate() {
|
||||
float t = 1f * (System.currentTimeMillis() - mStartTime) / mZoomDuration;
|
||||
t = Math.min(1f, t);
|
||||
t = mInterpolator.getInterpolation(t);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
private class FlingRunnable implements Runnable {
|
||||
|
||||
private final OverScroller mScroller;
|
||||
private int mCurrentX, mCurrentY;
|
||||
|
||||
public FlingRunnable(Context context) {
|
||||
mScroller = new OverScroller(context);
|
||||
}
|
||||
|
||||
public void cancelFling() {
|
||||
mScroller.forceFinished(true);
|
||||
}
|
||||
|
||||
public void fling(int viewWidth, int viewHeight, int velocityX,
|
||||
int velocityY) {
|
||||
final RectF rect = getDisplayRect();
|
||||
if (rect == null) {
|
||||
return;
|
||||
}
|
||||
final int startX = Math.round(-rect.left);
|
||||
final int minX, maxX, minY, maxY;
|
||||
if (viewWidth < rect.width()) {
|
||||
minX = 0;
|
||||
maxX = Math.round(rect.width() - viewWidth);
|
||||
} else {
|
||||
minX = maxX = startX;
|
||||
}
|
||||
final int startY = Math.round(-rect.top);
|
||||
if (viewHeight < rect.height()) {
|
||||
minY = 0;
|
||||
maxY = Math.round(rect.height() - viewHeight);
|
||||
} else {
|
||||
minY = maxY = startY;
|
||||
}
|
||||
mCurrentX = startX;
|
||||
mCurrentY = startY;
|
||||
// If we actually can move, fling the scroller
|
||||
if (startX != maxX || startY != maxY) {
|
||||
mScroller.fling(startX, startY, velocityX, velocityY, minX,
|
||||
maxX, minY, maxY, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mScroller.isFinished()) {
|
||||
return; // remaining post that should not be handled
|
||||
}
|
||||
if (mScroller.computeScrollOffset()) {
|
||||
final int newX = mScroller.getCurrX();
|
||||
final int newY = mScroller.getCurrY();
|
||||
mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);
|
||||
checkAndDisplayMatrix();
|
||||
mCurrentX = newX;
|
||||
mCurrentY = newY;
|
||||
// Post On animation
|
||||
Compat.postOnAnimation(mImageView, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ImageView;
|
||||
|
||||
class Util {
|
||||
|
||||
static void checkZoomLevels(float minZoom, float midZoom,
|
||||
float maxZoom) {
|
||||
if (minZoom >= midZoom) {
|
||||
throw new IllegalArgumentException(
|
||||
"Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value");
|
||||
} else if (midZoom >= maxZoom) {
|
||||
throw new IllegalArgumentException(
|
||||
"Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value");
|
||||
}
|
||||
}
|
||||
|
||||
static boolean hasDrawable(ImageView imageView) {
|
||||
return imageView.getDrawable() != null;
|
||||
}
|
||||
|
||||
static boolean isSupportedScaleType(final ImageView.ScaleType scaleType) {
|
||||
if (scaleType == null) {
|
||||
return false;
|
||||
}
|
||||
switch (scaleType) {
|
||||
case MATRIX:
|
||||
throw new IllegalStateException("Matrix scale type is not supported");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int getPointerIndex(int action) {
|
||||
return (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.github.chrisbanes.photoview;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,25 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google {
|
||||
content {
|
||||
includeGroupByRegex("com\\.android.*")
|
||||
includeGroupByRegex("com\\.google.*")
|
||||
includeGroupByRegex("androidx.*")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
|
||||
include ':EasyPlayerPro'
|
||||
include ':ijkplayer-java'
|
||||
include ':photoview'
|
||||
|
||||
Reference in New Issue
Block a user