├── Utils ├── app │ ├── .gitignore │ ├── libs │ │ ├── aws-android-sdk-1.4.6-core.jar │ │ ├── aws-android-sdk-1.4.6-s3.jar │ │ └── libGoogleAnalyticsServices.jar │ ├── src │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── res │ │ │ │ └── values │ │ │ │ │ └── color.xml │ │ │ └── java │ │ │ │ └── net │ │ │ │ └── the4thdimension │ │ │ │ └── android │ │ │ │ ├── FileUtils.java │ │ │ │ ├── AwsUtils.java │ │ │ │ ├── SharedPreferenceManager.java │ │ │ │ ├── YouTubeUtils.java │ │ │ │ ├── AudioUtils.java │ │ │ │ ├── ViewUtils.java │ │ │ │ ├── ImageUtils.java │ │ │ │ ├── DateUtils.java │ │ │ │ ├── MediaUtils.java │ │ │ │ └── Utils.java │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── net.the4thdimension.android │ │ │ │ ├── UtilsInstrumentationTest.java │ │ │ │ └── FileUtilsInstrumentationTest.java │ │ └── test │ │ │ └── java │ │ │ └── net │ │ │ └── the4thdimension │ │ │ └── android │ │ │ └── UtilsTest.java │ ├── proguard-rules.pro │ ├── gradle.properties │ └── build.gradle ├── settings.gradle ├── gradle │ ├── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew.bat │ └── gradlew ├── .settings │ └── org.eclipse.jdt.core.prefs ├── build.gradle ├── .gitignore ├── gradle.properties ├── gradlew.bat ├── maven_push.gradle └── gradlew ├── .gitignore ├── LICENSE └── README.md /Utils/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Utils/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /Utils/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaydeepw/android-utils/HEAD/Utils/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Utils/app/libs/aws-android-sdk-1.4.6-core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaydeepw/android-utils/HEAD/Utils/app/libs/aws-android-sdk-1.4.6-core.jar -------------------------------------------------------------------------------- /Utils/app/libs/aws-android-sdk-1.4.6-s3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaydeepw/android-utils/HEAD/Utils/app/libs/aws-android-sdk-1.4.6-s3.jar -------------------------------------------------------------------------------- /Utils/app/libs/libGoogleAnalyticsServices.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaydeepw/android-utils/HEAD/Utils/app/libs/libGoogleAnalyticsServices.jar -------------------------------------------------------------------------------- /Utils/gradle/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaydeepw/android-utils/HEAD/Utils/gradle/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Utils/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /Utils/gradle/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Oct 29 19:58:06 IST 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip 7 | -------------------------------------------------------------------------------- /Utils/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jul 08 10:55:56 IST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-milestone-1-all.zip 7 | -------------------------------------------------------------------------------- /Utils/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Utils/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/jay/android-sdks/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /Utils/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | // classpath 'com.android.tools.build:gradle:2.2.2' 10 | classpath 'com.android.tools.build:gradle:3.0.0-alpha5' 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | def isReleaseBuild() { 18 | return version.contains("SNAPSHOT") == false 19 | } 20 | 21 | allprojects { 22 | version = VERSION_NAME 23 | group = GROUP 24 | 25 | repositories { 26 | mavenCentral() 27 | } 28 | } 29 | 30 | apply plugin: 'android-reporting' 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #built application files 3 | *.apk 4 | *.ap_ 5 | 6 | # files for the dex VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # generated files 13 | bin/ 14 | gen/ 15 | 16 | # Local configuration file (sdk path, etc) 17 | local.properties 18 | 19 | # Windows thumbnail db 20 | Thumbs.db 21 | 22 | # OSX files 23 | .DS_Store 24 | 25 | # Eclipse project files 26 | .classpath 27 | .project 28 | 29 | # Android Studio 30 | .idea 31 | .idea/workspace.xml - remove # and delete .idea if it better suit your needs. 32 | .gradle 33 | build/ 34 | secring.gpg 35 | Optional - for older project format, add this section to your gitignore file: 36 | 37 | 38 | /*/out 39 | /*/*/build 40 | /*/*/production 41 | *.iws 42 | *.ipr 43 | *~ 44 | *.swp 45 | 46 | # The link below states that it is OK to 47 | # ignore app.iml and *.iml 48 | #http://stackoverflow.com/a/26363300/452487 49 | app/app.iml 50 | *.iml 51 | -------------------------------------------------------------------------------- /Utils/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #built application files 3 | *.apk 4 | *.ap_ 5 | 6 | # files for the dex VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # generated files 13 | bin/ 14 | gen/ 15 | 16 | # Local configuration file (sdk path, etc) 17 | local.properties 18 | 19 | # Windows thumbnail db 20 | Thumbs.db 21 | 22 | # OSX files 23 | .DS_Store 24 | 25 | # Eclipse project files 26 | .classpath 27 | .project 28 | 29 | # Android Studio 30 | .idea 31 | .idea/workspace.xml - remove # and delete .idea if it better suit your needs. 32 | .gradle 33 | build/ 34 | secring.gpg 35 | Optional - for older project format, add this section to your gitignore file: 36 | 37 | 38 | /*/out 39 | /*/*/build 40 | /*/*/production 41 | *.iws 42 | *.ipr 43 | *~ 44 | *.swp 45 | 46 | # The link below states that it is OK to 47 | # ignore app.iml and *.iml 48 | #http://stackoverflow.com/a/26363300/452487 49 | app/app.iml 50 | *.iml 51 | -------------------------------------------------------------------------------- /Utils/app/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | POM_NAME=AndroidUtils 20 | 21 | # beware. Don not change this artifact ID. This is refered to when the user add this library as a dependency. 22 | POM_ARTIFACT_ID=android-utils 23 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /Utils/app/src/main/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #FFFFFF 5 | #FFFF00 6 | #FF00FF 7 | #FF0000 8 | #C0C0C0 9 | #808080 10 | #808000 11 | #800080 12 | #800000 13 | #00FFFF 14 | #00FF00 15 | #008080 16 | #008000 17 | #0000FF 18 | #000080 19 | #000000 20 | #FFA500 21 | #CCCCCC 22 | #E5E4E2 23 | #00CC66 24 | #5a5959 25 | #488AC7 26 | #728FCE 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jaydeep 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Utils/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "25.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 21 10 | versionCode Integer.parseInt(project.VERSION_CODE); 11 | versionName project.VERSION_NAME 12 | 13 | testInstrumentationRunner "android.test.InstrumentationTestRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | 22 | // It would be better to fix the issues 23 | lintOptions { 24 | abortOnError false 25 | } 26 | } 27 | 28 | dependencies { 29 | compile 'com.android.support:support-annotations:23.0.0' 30 | 31 | // Unit testing dependencies 32 | testCompile 'junit:junit:4.12' 33 | 34 | androidTestCompile 'junit:junit:4.12' 35 | androidTestCompile 'com.android.support.test:runner:0.5' 36 | androidTestCompile 'com.android.support.test:rules:0.5' 37 | testCompile "org.mockito:mockito-core:1.9.5" 38 | } 39 | 40 | apply from: '../maven_push.gradle' 41 | -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/FileUtils.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | 6 | /** 7 | * Created by jaydeepw on 12/5/16. 8 | */ 9 | 10 | public class FileUtils { 11 | 12 | /** 13 | * List the files in the parameter directory. 14 | * @param directoryName 15 | * @param files 16 | */ 17 | public static void listFiles(String directoryName, ArrayList files) { 18 | File directory = new File(directoryName); 19 | listFiles(directory, files); 20 | 21 | /* // get all the files from a directory 22 | File[] fList = directory.listFiles(); 23 | for (File file : fList) { 24 | if (file.isFile()) { 25 | files.add(file); 26 | } else if (file.isDirectory()) { 27 | listFiles(file.getAbsolutePath(), files); 28 | } 29 | }*/ 30 | } 31 | 32 | /** 33 | * List the files in the parameter directory. 34 | * @param files 35 | */ 36 | public static void listFiles(File directory, ArrayList files) { 37 | 38 | // get all the files from a directory 39 | File[] fList = directory.listFiles(); 40 | for (File file : fList) { 41 | if (file.isFile()) { 42 | files.add(file); 43 | } else if (file.isDirectory()) { 44 | listFiles(file.getAbsolutePath(), files); 45 | } 46 | } // end for 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Utils/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | VERSION_NAME=3.0.2 20 | VERSION_CODE=6 21 | GROUP=net.the4thdimension 22 | 23 | POM_DESCRIPTION=Collection of Android utility classes that will make us all productive during app development 24 | POM_URL=https://github.com/changer/android-utils 25 | POM_SCM_URL=https://github.com/changer/android-utils 26 | POM_SCM_CONNECTION=scm:git@github.com:changer/android-utils.git 27 | POM_SCM_DEV_CONNECTION=scm:git@github.com:changer/android-utils.git 28 | POM_LICENCE_NAME=The MIT License (MIT) 29 | POM_LICENCE_URL=http://opensource.org/licenses/MIT 30 | POM_LICENCE_DIST=repo 31 | POM_DEVELOPER_ID=jaydeepw 32 | POM_DEVELOPER_NAME=Jaydeep Wagh -------------------------------------------------------------------------------- /Utils/app/src/androidTest/java/net.the4thdimension.android/UtilsInstrumentationTest.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import android.test.AndroidTestCase; 4 | 5 | /** 6 | * Created by jay on 25/7/15. 7 | */ 8 | public class UtilsInstrumentationTest extends AndroidTestCase { 9 | 10 | public void testAppVersionNumber() throws Exception { 11 | String applicationVersionNumber = Utils.getApplicationVersionNumber(null); 12 | String expected = null; 13 | 14 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 15 | // use this method because float is not precise 16 | assertEquals("App version invalid", expected, applicationVersionNumber); 17 | } 18 | 19 | public void testIsValidUrlWithValidUrl() throws Exception { 20 | boolean isValid = Utils.isValidURL("http://jay.com/"); 21 | boolean expected = true; 22 | 23 | assertEquals("Url invalid", expected, isValid); 24 | } 25 | 26 | public void testIsValidUrlWithInvalidUrl() throws Exception { 27 | boolean isValid = Utils.isValidURL("//jay.com/"); 28 | boolean expected = false; 29 | 30 | assertEquals("Url invalid", expected, isValid); 31 | } 32 | 33 | public void testIsValidUrlWithSchemeOnly() throws Exception { 34 | boolean isValid = Utils.isValidURL("http://"); 35 | boolean expected = false; 36 | 37 | assertEquals("Url invalid", expected, isValid); 38 | } 39 | 40 | public void testIsValidUrlWithoutScheme() throws Exception { 41 | boolean isValid = Utils.isValidURL("www.jay.com"); 42 | boolean expected = false; 43 | 44 | assertEquals("Url invalid", expected, isValid); 45 | } 46 | } -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/AwsUtils.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import android.util.Base64; 4 | 5 | import java.security.SignatureException; 6 | 7 | import javax.crypto.Mac; 8 | import javax.crypto.spec.SecretKeySpec; 9 | 10 | public class AwsUtils { 11 | 12 | /*** 13 | * Computes RFC 2104-compliant HMAC signature. This can be used to sign the Amazon S3 14 | * request urls 15 | * 16 | * @param data The data to be signed. 17 | * @param key The signing key. 18 | * @return The Base64-encoded RFC 2104-compliant HMAC signature. 19 | * @throws java.security.SignatureException when signature generation fails 20 | */ 21 | public static String getHMac(String data, String key) throws SignatureException { 22 | 23 | if (data == null) { 24 | throw new NullPointerException("Data to be signed cannot be null"); 25 | } 26 | 27 | String result = null; 28 | try { 29 | 30 | final String HMAC_SHA1_ALGORITHM = "HmacSHA1"; 31 | 32 | // get an hmac_sha1 key from the raw key bytes 33 | SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM); 34 | 35 | // get an hmac_sha1 Mac instance & 36 | // initialize with the signing key 37 | Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM); 38 | mac.init(signingKey); 39 | 40 | // compute the hmac on input data bytes 41 | byte[] digest = mac.doFinal(data.getBytes()); 42 | 43 | if (digest != null) { 44 | // Base 64 Encode the results 45 | result = Base64.encodeToString(digest, Base64.NO_WRAP); 46 | } 47 | 48 | } catch (Exception e) { 49 | throw new SignatureException("Failed to generate HMAC : " + e.getMessage()); 50 | } 51 | 52 | return result; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Utils/app/src/androidTest/java/net.the4thdimension.android/FileUtilsInstrumentationTest.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import android.os.Environment; 4 | import android.support.test.runner.AndroidJUnit4; 5 | import android.test.AndroidTestCase; 6 | import android.test.suitebuilder.annotation.SmallTest; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import java.io.File; 12 | import java.util.ArrayList; 13 | 14 | /** 15 | * Created by jaydeepw on 1/2/17. 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | @SmallTest 19 | public class FileUtilsInstrumentationTest extends AndroidTestCase { 20 | 21 | @Test 22 | public void listFilesMultiple() throws Exception { 23 | 24 | File tempFile = new File(Environment.getExternalStorageDirectory().getPath()); 25 | File directory = new File(tempFile, "rajababu"); 26 | boolean isDirCreated = directory.mkdir(); 27 | assertEquals("Directory created", true, isDirCreated); 28 | 29 | File file1 = new File(directory, "f1.txt"); 30 | File file2 = new File(directory, "f2.txt"); 31 | file1.createNewFile(); 32 | file2.createNewFile(); 33 | 34 | ArrayList files = new ArrayList(); 35 | FileUtils.listFiles(directory, files); 36 | 37 | assertEquals(2, files.size()); 38 | 39 | // clean up 40 | file1.delete(); 41 | file2.delete(); 42 | directory.delete(); 43 | } 44 | 45 | @Test 46 | public void listFilesZeroFiles() throws Exception { 47 | 48 | File tempFile = new File(Environment.DIRECTORY_DOWNLOADS); 49 | File directory = new File(tempFile, "rajababu"); 50 | directory.mkdir(); 51 | 52 | ArrayList files = new ArrayList(); 53 | FileUtils.listFiles(directory, files); 54 | 55 | assertEquals(0, files.size()); 56 | 57 | // clean up 58 | directory.delete(); 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /Utils/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /Utils/gradle/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /Utils/maven_push.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven' 2 | apply plugin: 'signing' 3 | 4 | def sonatypeRepositoryUrl 5 | if (isReleaseBuild()) { 6 | println 'RELEASE BUILD' 7 | sonatypeRepositoryUrl = hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL 8 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 9 | } else { 10 | println 'DEBUG BUILD' 11 | sonatypeRepositoryUrl = hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL 12 | : "https://oss.sonatype.org/content/repositories/snapshots/" 13 | } 14 | 15 | def getRepositoryUsername() { 16 | return hasProperty('nexusUsername') ? nexusUsername : "" 17 | } 18 | 19 | def getRepositoryPassword() { 20 | return hasProperty('nexusPassword') ? nexusPassword : "" 21 | } 22 | 23 | afterEvaluate { project -> 24 | uploadArchives { 25 | repositories { 26 | mavenDeployer { 27 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 28 | 29 | pom.artifactId = POM_ARTIFACT_ID 30 | 31 | repository(url: sonatypeRepositoryUrl) { 32 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 33 | } 34 | 35 | pom.project { 36 | name POM_NAME 37 | packaging POM_PACKAGING 38 | description POM_DESCRIPTION 39 | url POM_URL 40 | 41 | scm { 42 | url POM_SCM_URL 43 | connection POM_SCM_CONNECTION 44 | developerConnection POM_SCM_DEV_CONNECTION 45 | } 46 | 47 | licenses { 48 | license { 49 | name POM_LICENCE_NAME 50 | url POM_LICENCE_URL 51 | distribution POM_LICENCE_DIST 52 | } 53 | } 54 | 55 | developers { 56 | developer { 57 | id POM_DEVELOPER_ID 58 | name POM_DEVELOPER_NAME 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | signing { 67 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } 68 | sign configurations.archives 69 | } 70 | 71 | task androidJavadocs(type: Javadoc) { 72 | source = android.sourceSets.main.java.sourceFiles 73 | } 74 | 75 | task androidJavadocsJar(type: Jar) { 76 | classifier = 'javadoc' 77 | //basename = artifact_id 78 | from androidJavadocs.destinationDir 79 | } 80 | 81 | task androidSourcesJar(type: Jar) { 82 | classifier = 'sources' 83 | //basename = artifact_id 84 | from android.sourceSets.main.java.sourceFiles 85 | } 86 | 87 | artifacts { 88 | //archives packageReleaseJar 89 | archives androidSourcesJar 90 | archives androidJavadocsJar 91 | } 92 | } -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/SharedPreferenceManager.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.content.SharedPreferences.Editor; 6 | 7 | /** 8 | * Provides convenience methods and abstraction for storing data in the 9 | * {@link android.content.SharedPreferences} 10 | *

11 | *
12 | *
13 | * 14 | * @author Jay 15 | **/ 16 | public class SharedPreferenceManager { 17 | 18 | protected Context mContext; 19 | 20 | // TODO: make these members private. 21 | protected SharedPreferences mSettings; 22 | protected Editor mEditor; 23 | 24 | public SharedPreferenceManager(Context ctx, String prefFileName) { 25 | mContext = ctx; 26 | 27 | mSettings = mContext.getSharedPreferences(prefFileName, 28 | Context.MODE_PRIVATE); 29 | mEditor = mSettings.edit(); 30 | } 31 | 32 | /*** 33 | * Set a value for the key 34 | ****/ 35 | public void setValue(String key, String value) { 36 | mEditor.putString(key, value); 37 | mEditor.commit(); 38 | } 39 | 40 | /*** 41 | * Set a value for the key 42 | ****/ 43 | public void setValue(String key, int value) { 44 | mEditor.putInt(key, value); 45 | mEditor.commit(); 46 | } 47 | 48 | /*** 49 | * Set a value for the key 50 | ****/ 51 | public void setValue(String key, double value) { 52 | setValue(key, Double.toString(value)); 53 | } 54 | 55 | /*** 56 | * Set a value for the key 57 | ****/ 58 | public void setValue(String key, long value) { 59 | mEditor.putLong(key, value); 60 | mEditor.commit(); 61 | } 62 | 63 | /**** 64 | * Gets the value from the settings stored natively on the device. 65 | * 66 | * @param defaultValue Default value for the key, if one is not found. 67 | **/ 68 | public String getValue(String key, String defaultValue) { 69 | return mSettings.getString(key, defaultValue); 70 | } 71 | 72 | public int getIntValue(String key, int defaultValue) { 73 | return mSettings.getInt(key, defaultValue); 74 | } 75 | 76 | public long getLongValue(String key, long defaultValue) { 77 | return mSettings.getLong(key, defaultValue); 78 | } 79 | 80 | /**** 81 | * Gets the value from the preferences stored natively on the device. 82 | * 83 | * @param defValue Default value for the key, if one is not found. 84 | **/ 85 | public boolean getValue(String key, boolean defValue) { 86 | return mSettings.getBoolean(key, defValue); 87 | } 88 | 89 | public void setValue(String key, boolean value) { 90 | mEditor.putBoolean(key, value); 91 | mEditor.commit(); 92 | } 93 | 94 | /** 95 | * Clear all the preferences store in this {@link android.content.SharedPreferences.Editor} 96 | */ 97 | public boolean clear() { 98 | try { 99 | mEditor.clear().commit(); 100 | return true; 101 | } catch (Exception e) { 102 | e.printStackTrace(); 103 | return false; 104 | } 105 | } 106 | 107 | /** 108 | * Removes preference entry for the given key. 109 | * 110 | * @param key 111 | */ 112 | public void removeValue(String key) { 113 | if (mEditor != null) { 114 | mEditor.remove(key).commit(); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/YouTubeUtils.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import android.net.Uri; 4 | import android.text.TextUtils; 5 | 6 | import java.net.MalformedURLException; 7 | import java.net.URL; 8 | 9 | /** 10 | * YouTube related utility class. 11 | */ 12 | public class YouTubeUtils { 13 | 14 | /*default.jpg - default 15 | https://i1.ytimg.com/vi//mqdefault.jpg - medium 16 | https://i1.ytimg.com/vi//hqdefault.jpg - high 17 | https://i1.ytimg.com/vi//sddefault.jpg 18 | */ 19 | public static final String THUMBNAIL_QUALITY_DEFAULT = "default"; 20 | public static final String THUMBNAIL_QUALITY_MQ = "mqdefault"; 21 | public static final String THUMBNAIL_QUALITY_HQ = "hqdefault"; 22 | public static final String THUMBNAIL_QUALITY_SD = "sddefault"; 23 | 24 | public static String createVideoUrl(String videoId) { 25 | 26 | if(TextUtils.isEmpty(videoId)) { 27 | throw new IllegalArgumentException("Video Id cannot be null or blank"); 28 | } 29 | 30 | return "http://youtube.com/watch?v=" + videoId; 31 | } 32 | 33 | /** 34 | * Creates thubmnail url for a given video ID. 35 | * 36 | * @param videoId 37 | * @param quality 38 | **/ 39 | public static String createThumbnailUrl(String videoId, String quality) { 40 | 41 | if(quality == null) { 42 | quality = THUMBNAIL_QUALITY_DEFAULT; 43 | } 44 | 45 | if(!quality.equalsIgnoreCase(THUMBNAIL_QUALITY_DEFAULT) && 46 | !quality.equalsIgnoreCase(THUMBNAIL_QUALITY_MQ) && 47 | !quality.equalsIgnoreCase(THUMBNAIL_QUALITY_HQ) && 48 | !quality.equalsIgnoreCase(THUMBNAIL_QUALITY_SD)) { 49 | throw new IllegalArgumentException("Invalid quality thumbnail requested"); 50 | } 51 | 52 | return "http://img.youtube.com/vi/" + videoId + "/" + quality + ".jpg"; 53 | } 54 | 55 | /**** 56 | * Checks to see if the your contains the authority "youtube.com" 57 | ****/ 58 | public static boolean isYouTubeUrl(String url) { 59 | 60 | if(TextUtils.isEmpty(url)) { 61 | return false; 62 | } 63 | 64 | Uri uri = Uri.parse(url); 65 | String authority = uri.getAuthority(); 66 | if( !TextUtils.isEmpty(authority) && authority.contains("youtube.com")) { 67 | return true; 68 | } else { 69 | return false; 70 | } 71 | } 72 | 73 | /** 74 | * Fetches video ID from given you tube video URL. 75 | * 76 | * @param videoUrl 77 | * @return video ID 78 | */ 79 | public static String getVideoId(String videoUrl) { 80 | String videoId = null; 81 | 82 | // Sample YouTube URLs. 83 | // "http://www.youtube.com/watch?v=8mKTiD02v3M"; 84 | // "http://www.youtube.com/v/8mKTiD02v3M?version=3&autohide=1"; 85 | // "http://youtu.be/8mKTiD02v3M"; 86 | 87 | URL url; 88 | try { 89 | 90 | url = new URL(videoUrl); 91 | 92 | if (!TextUtils.isEmpty(videoUrl)) { 93 | if (videoUrl.contains("?v=")) { 94 | videoId = videoUrl.split("\\?v=")[1]; 95 | } else if (videoUrl.contains("?version")) { 96 | videoId = url.getPath().split("\\/")[2]; 97 | } else { 98 | videoId = url.getPath().split("\\/")[1]; 99 | } 100 | } 101 | } catch (MalformedURLException e) { 102 | e.printStackTrace(); 103 | } catch (Exception e) { 104 | e.printStackTrace(); 105 | } 106 | 107 | return videoId; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android Utilities 2 | ============= 3 | 4 | Library Project for utility classes that can make me(and others) more productive. 5 | AndroidUtils requires Android 4.0+. 6 | 7 | 8 | **Utility classes included** 9 | 10 | * Utils - Set of general purpose utility methods. 11 | * FileUtils - Set of general purpose utility methods for file operation. 12 | * MediaUtils - Set of utilities to handle media resize, scaling, rotation and other relevant stuff. 13 | * ViewUtils - Set of utilities to handle Android Views' related stuff. 14 | * ImageUtils - Set of utilities to handle image manipulation. 15 | * AudioUtils - Set of utilities to handle audio recording, playing and saving to disk. 16 | * DateUtils - Set of utilities to handle date manipulation. 17 | * StorageManager - Android SharedPreferences abstraction. 18 | * YouTubeUtils - Set of utilities to handle YouTube related stuff. 19 | 20 | ---- 21 | 22 | Download 23 | -------- 24 | Gradle: 25 | ```groovy 26 | compile 'com.github.jaydeepw:android-utils:3.0.6' 27 | ``` 28 | 29 | Donations! 30 | ========== 31 | * **Using Bitcoins**: If this project has helped you understand issues, be productive by using this library in your app or just being nice with me, you can always donate me Bitcoins at this address `3QJEmgqXsT1CFLtURYWxzmww59DdKYVwNk` 32 | 33 | * **Using Paypal**: [Pay Jay](https://www.paypal.me/jaydeepw) 34 | 35 | 36 | Changelog 37 | ============ 38 | 39 | ## v3.0.6 40 | 41 | Method count: 506 42 | 43 | JAR size: 46KB 44 | 45 | * Fix memory leak when calling methods in Utils class. 46 | 47 | ## v3.0.4 48 | 49 | Method count: 506 50 | 51 | JAR size: 46KB 52 | 53 | * fix [#2](https://github.com/jaydeepw/android-utils/issues/2). Overload showAlert/showDialog methods with resId parameter 54 | * fix [#12](https://github.com/jaydeepw/android-utils/issues/12). Use try catch and return boolean in sharePreferenceManger#clear method. 55 | * fix [#11](https://github.com/jaydeepw/android-utils/issues/11). Add file list utils method to FileUtils class. 56 | 57 | ## v3.0.2 58 | 59 | Method count: 11837 60 | 61 | JAR size: 56KB 62 | 63 | * fix [#10](https://github.com/jaydeepw/android-utils/issues/10). Remove unnecessary app_icon and strings. 64 | 65 | ## v3.0.1 66 | 67 | * add hideKeyboard() to programmatically hide keyboard in the UI 68 | * add setTextValues() and getNullEmptyCheckedValue() methods to help displaying text without worrying about null value check in the UI 69 | * add method capitalizeString() to completely or partially capitalize the characters in the string 70 | * add method toBold() to partially or completely typeface a string as bold 71 | * add crypto helper methods getSha512Hash(String) and getSha512Hash(byte[]) to generate SHA hash 72 | * add getExtension() for a file helper method 73 | * add isBuildBelow() to quickly compare agains given Android API level 74 | 75 | 76 | The MIT License 77 | ============= 78 | 79 | **Copyright (c) 2016 Jaydeep** 80 | 81 | Permission is hereby granted, free of charge, to any person obtaining a copy 82 | of this software and associated documentation files (the "Software"), to deal 83 | in the Software without restriction, including without limitation the rights 84 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 85 | copies of the Software, and to permit persons to whom the Software is 86 | furnished to do so, subject to the following conditions: 87 | 88 | The above copyright notice and this permission notice shall be included in 89 | all copies or substantial portions of the Software. 90 | 91 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 92 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 93 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 94 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 95 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 96 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 97 | THE SOFTWARE. 98 | -------------------------------------------------------------------------------- /Utils/app/src/test/java/net/the4thdimension/android/UtilsTest.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import android.content.Context; 4 | import android.test.mock.MockContext; 5 | 6 | import junit.framework.TestCase; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.mockito.Mock; 11 | import org.mockito.Mockito; 12 | 13 | /** 14 | * Created by jay on 25/7/15. 15 | */ 16 | public class UtilsTest extends TestCase { 17 | 18 | private MockContext mockContext = new MockContext(); 19 | 20 | @Test 21 | public void testFormatSizeKb() throws Exception { 22 | String formattedSize = Utils.formatSize(1024); 23 | // expected value is 212 24 | String expected = "1 KB"; 25 | 26 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 27 | // use this method because float is not precise 28 | assertEquals("Conversion from bytes to KB", expected, 29 | formattedSize); 30 | } 31 | 32 | @Test 33 | public void testFormatSizeMb() throws Exception { 34 | String formattedSize = Utils.formatSize(1024*1024); 35 | String expected = "1 MB"; 36 | 37 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 38 | // use this method because float is not precise 39 | assertEquals("Conversion from bytes to MB", expected, 40 | formattedSize); 41 | } 42 | 43 | @Test 44 | public void testCapitalizeString() throws Exception { 45 | String stringToCap = "this is awesome"; 46 | String capitalizedString = Utils.capitalizeString(stringToCap); 47 | String expected = "This Is Awesome"; 48 | 49 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 50 | // use this method because float is not precise 51 | assertEquals("Capitalization failed", expected, 52 | capitalizedString); 53 | } 54 | 55 | @Test 56 | public void testCapitalizeStringForNull() throws Exception { 57 | String stringToCap = null; 58 | String capitalizedString = Utils.capitalizeString(stringToCap); 59 | String expected = null; 60 | 61 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 62 | // use this method because float is not precise 63 | assertEquals("Capitalization failed", expected, 64 | capitalizedString); 65 | } 66 | 67 | @Test 68 | public void testCapitalizeStringForEmpty() throws Exception { 69 | String stringToCap = ""; 70 | String capitalizedString = Utils.capitalizeString(stringToCap); 71 | String expected = ""; 72 | 73 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 74 | // use this method because float is not precise 75 | assertEquals("Capitalization failed", expected, 76 | capitalizedString); 77 | } 78 | 79 | @Test 80 | public void testIsValidEmailTrue() throws Exception { 81 | boolean valid = Utils.isValidEmail("jay@twitter.com"); 82 | boolean expected = true; 83 | 84 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 85 | // use this method because float is not precise 86 | assertEquals("Email invalid", expected, 87 | valid); 88 | } 89 | 90 | @Test 91 | public void testIsValidEmailFalse() throws Exception { 92 | boolean invalid = Utils.isValidEmail("jay@twitter"); 93 | boolean expected = false; 94 | 95 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 96 | // use this method because float is not precise 97 | assertEquals("Email invalid", expected, 98 | invalid); 99 | } 100 | 101 | @Mock 102 | Context mContext; 103 | 104 | /*@Test 105 | public void test() throws Exception { 106 | String applicationVersionNumber = Utils.getApplicationVersionNumber(mContext); 107 | String expected = "1.2.3"; 108 | 109 | // Log.i(TAG, "formattedSize: " + formattedSize + " expected: " + expected); 110 | // use this method because float is not precise 111 | assertEquals("App version invalid", expected, applicationVersionNumber); 112 | }*/ 113 | } -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/AudioUtils.java: -------------------------------------------------------------------------------- 1 | 2 | package net.the4thdimension.android; 3 | 4 | import android.content.ContentValues; 5 | import android.content.Context; 6 | import android.media.MediaRecorder; 7 | import android.net.Uri; 8 | import android.provider.MediaStore; 9 | import android.text.TextUtils; 10 | import android.util.Log; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.util.Date; 15 | 16 | /** 17 | * 18 | */ 19 | public class AudioUtils { 20 | 21 | private static final String TAG = AudioUtils.class.getSimpleName(); 22 | 23 | private static String mFileName; 24 | private static MediaRecorder mRecorder; 25 | 26 | public static void startRecordingAudio(Context ctx) { 27 | 28 | mRecorder = new MediaRecorder(); 29 | mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 30 | mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 31 | // Winamp does not play the 32 | // audio recorded MP3 audio. 33 | mFileName = Utils.getStorageDirectory(ctx, "application-utils/audio").getAbsolutePath() + "/" + new Date().getTime() + ".mp3"; 34 | mRecorder.setOutputFile(mFileName); 35 | mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); 36 | 37 | try { 38 | mRecorder.prepare(); 39 | mRecorder.start(); 40 | } catch (IllegalStateException e) { 41 | Log.e(TAG, " failed" + e.getMessage()); 42 | } catch (IOException e) { 43 | Log.e(TAG, " failed" + e.getMessage()); 44 | } catch (Exception e) { 45 | Log.e(TAG, " failed" + e.getMessage()); 46 | } 47 | } 48 | 49 | public static Uri stopRecordingAudio(Context ctx) { 50 | 51 | try { 52 | mRecorder.stop(); 53 | mRecorder.reset(); // set state to idle 54 | mRecorder.release(); 55 | mRecorder = null; 56 | } catch (Exception e) { 57 | e.printStackTrace(); 58 | } 59 | 60 | return saveAudio(ctx); 61 | } 62 | 63 | /** 64 | * 65 | * @deprecated 66 | *
67 | * Use {@link nl.changer.android.opensource.AudioUtils#saveAudio(android.content.Context)} 68 | * Insert an audio into {@link android.provider.MediaStore.Images.Media} content provider of the device. 69 | * 70 | * @return The media content Uri to the newly created audio, or null if failed for any reason. 71 | * ***/ 72 | public static Uri writeAudioToMedia(Context ctx, File audioFile) { 73 | ContentValues values = new ContentValues(); 74 | values.put(MediaStore.MediaColumns.DATA, audioFile.getAbsolutePath()); 75 | values.put(MediaStore.MediaColumns.TITLE, ""); 76 | values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mpeg"); 77 | values.put(MediaStore.MediaColumns.SIZE, audioFile.length()); 78 | values.put(MediaStore.Audio.Media.ARTIST, ""); 79 | values.put(MediaStore.Audio.Media.IS_RINGTONE, false); 80 | // Now set some extra features it depend on you 81 | values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false); 82 | values.put(MediaStore.Audio.Media.IS_ALARM, false); 83 | values.put(MediaStore.Audio.Media.IS_MUSIC, false); 84 | 85 | Uri uri = MediaStore.Audio.Media.getContentUriForPath(audioFile.getAbsolutePath()); 86 | Uri uri2 = ctx.getContentResolver().insert(uri, values); 87 | 88 | if (uri2 == null || TextUtils.isEmpty(uri2.toString())) { 89 | Log.w(TAG, "Something went wrong while inserting data to content resolver"); 90 | } 91 | 92 | return uri2; 93 | } 94 | 95 | /** 96 | * 97 | * @param ctx 98 | * @return The media content Uri to the newly created audio, or null if failed for any reason. 99 | */ 100 | private static Uri saveAudio(Context ctx) { 101 | File audioFile = new File(mFileName); 102 | 103 | ContentValues values = new ContentValues(); 104 | values.put(MediaStore.MediaColumns.DATA, audioFile.getAbsolutePath()); 105 | values.put(MediaStore.MediaColumns.TITLE, ""); 106 | values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mpeg"); 107 | values.put(MediaStore.MediaColumns.SIZE, audioFile.length()); 108 | values.put(MediaStore.Audio.Media.ARTIST, ""); 109 | values.put(MediaStore.Audio.Media.IS_RINGTONE, false); 110 | // Now set some extra features it depend on you 111 | values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false); 112 | values.put(MediaStore.Audio.Media.IS_ALARM, false); 113 | values.put(MediaStore.Audio.Media.IS_MUSIC, false); 114 | 115 | Uri uri = MediaStore.Audio.Media.getContentUriForPath(audioFile.getAbsolutePath()); 116 | Uri uri2 = ctx.getContentResolver().insert(uri, values); 117 | 118 | if (uri2 == null || TextUtils.isEmpty(uri2.toString())) { 119 | Log.w(TAG, "Something went wrong while inserting data to content resolver"); 120 | } 121 | 122 | return uri2; 123 | } 124 | 125 | /**** 126 | * Remove audio file that is existing on the device. 127 | * 128 | * @param ctx 129 | * {@link android.content.Context} 130 | * @param uri 131 | * {@link android.net.Uri} of the audio file 132 | * 133 | * @throws NullPointerException 134 | * if the Uri parameter is null 135 | * */ 136 | public static boolean removeAudio(Context ctx, Uri uri) { 137 | 138 | if (uri == null) { 139 | throw new NullPointerException("Uri cannot be null"); 140 | } 141 | 142 | return (ctx.getContentResolver().delete(uri, null, null) != 0); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /Utils/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /Utils/gradle/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/ViewUtils.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.graphics.Bitmap; 7 | import android.graphics.BitmapFactory; 8 | import android.graphics.Shader; 9 | import android.graphics.drawable.BitmapDrawable; 10 | import android.graphics.drawable.Drawable; 11 | import android.os.Build; 12 | import android.text.Editable; 13 | import android.text.InputFilter; 14 | import android.text.TextWatcher; 15 | import android.util.Log; 16 | import android.view.View; 17 | import android.widget.EditText; 18 | import android.widget.TextView; 19 | 20 | 21 | /** 22 | * Provides utility methods and convenience methods for View controls. 23 | *

24 | *

25 | * 26 | * @author Jay 27 | */ 28 | public class ViewUtils { 29 | 30 | private static final String TAG = ViewUtils.class.getSimpleName(); 31 | 32 | /** 33 | * Shows live character counter for the number of characters typed in the parameter {@link android.widget.EditText} 34 | * 35 | * @param editTextView Characters to count from 36 | * @param textCounterView {@link android.widget.TextView} to show live character count in 37 | * @param maxCharCount Max characters that can be typed in into the parameter edittext 38 | * @param countdown if true, only the remaining of the max character count will be displayed. If false, 39 | * current character count as well as max character count will be displayed in the UI. 40 | */ 41 | public static void setLiveCharCounter(EditText editTextView, final TextView textCounterView, final int maxCharCount, final boolean countdown) { 42 | 43 | if (editTextView == null) { 44 | throw new NullPointerException("View to count text characters on cannot be null"); 45 | } 46 | 47 | if (textCounterView == null) { 48 | throw new NullPointerException("View to display count cannot be null"); 49 | } 50 | 51 | // initialize the TextView initial state 52 | if (countdown) { 53 | textCounterView.setText(String.valueOf(maxCharCount)); 54 | } else { 55 | textCounterView.setText(String.valueOf("0 / " + maxCharCount)); 56 | } 57 | 58 | // initialize the edittext 59 | setMaxLength(editTextView, maxCharCount); 60 | 61 | editTextView.addTextChangedListener(new TextWatcher() { 62 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 63 | 64 | } 65 | 66 | public void onTextChanged(CharSequence s, int start, int before, int count) { 67 | 68 | if (countdown) { 69 | // show only the remaining number of characters 70 | int charsLeft = maxCharCount - s.length(); 71 | 72 | if (charsLeft >= 0) { 73 | textCounterView.setText(String.valueOf(charsLeft)); 74 | } 75 | } else { 76 | // show number of chars / maxChars in the UI 77 | textCounterView.setText(s.length() + " / " + maxCharCount); 78 | } 79 | 80 | } 81 | 82 | public void afterTextChanged(Editable s) { 83 | 84 | } 85 | }); 86 | } 87 | 88 | /** 89 | * Set max text length for textview 90 | */ 91 | public static void setMaxLength(TextView textView, int maxLength) { 92 | 93 | if (textView == null) { 94 | throw new NullPointerException("TextView cannot be null"); 95 | } 96 | 97 | InputFilter[] fArray = new InputFilter[1]; 98 | fArray[0] = new InputFilter.LengthFilter(maxLength); 99 | textView.setFilters(fArray); 100 | } 101 | 102 | /** 103 | * Tiles the background of the for a view with viewId as a parameter. 104 | */ 105 | public static void tileBackground(Context ctx, int viewId, int resIdOfTile) { 106 | 107 | try { 108 | // Tiling the background. 109 | Bitmap bmp = BitmapFactory.decodeResource(ctx.getResources(), resIdOfTile); 110 | BitmapDrawable bitmapDrawable = new BitmapDrawable(ctx.getResources(), bmp); 111 | bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 112 | View view = ((Activity) ctx).findViewById(viewId); 113 | 114 | if (view == null) { 115 | throw new NullPointerException("View to which the tile has to be applied should not be null"); 116 | } else { 117 | setBackground(view, bitmapDrawable); 118 | } 119 | } catch (Exception e) { 120 | Log.w(TAG, "#tileBackground Exception while tiling the background of the view"); 121 | } 122 | } 123 | 124 | @Deprecated 125 | /** 126 | * Use {@link ViewCompat#setBackground(view, background);} instead. 127 | * Sets the passed-in drawable parameter as a background to the 128 | * passed in target parameter in an SDK independent way. This 129 | * is the recommended way of setting background rather 130 | * than using native background setters provided by {@link android.view.View} 131 | * class. This method should NOT be used for setting background of an {@link android.widget.ImageView} 132 | * 133 | * @param target View to set background to. 134 | * @param drawable background image 135 | */ 136 | @SuppressLint("NewApi") 137 | public static void setBackground(View target, Drawable drawable) { 138 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 139 | target.setBackgroundDrawable(drawable); 140 | } else { 141 | target.setBackground(drawable); 142 | } 143 | } 144 | 145 | public static void tileBackground(Context ctx, int layoutId, View viewToTileBg, int resIdOfTile) { 146 | 147 | try { 148 | // Tiling the background. 149 | Bitmap bmp = BitmapFactory.decodeResource(ctx.getResources(), resIdOfTile); 150 | // deprecated constructor 151 | // BitmapDrawable bitmapDrawable = new BitmapDrawable(bmp); 152 | BitmapDrawable bitmapDrawable = new BitmapDrawable(ctx.getResources(), bmp); 153 | bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 154 | View view = viewToTileBg.findViewById(layoutId); 155 | 156 | if (view != null) { 157 | setBackground(view, bitmapDrawable); 158 | } 159 | 160 | } catch (Exception e) { 161 | Log.e(TAG, "Exception while tiling the background of the view"); 162 | } 163 | } 164 | 165 | /** 166 | * Set style to the parameter text view considering the current build SDK version. 167 | * 168 | * @param activity 169 | * @param textView 170 | * @param style 171 | */ 172 | public static void setStyle(Activity activity, TextView textView, 173 | int style) { 174 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 175 | textView.setTextAppearance(style); 176 | } else { 177 | textView.setTextAppearance(activity, style); 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/ImageUtils.java: -------------------------------------------------------------------------------- 1 | 2 | package net.the4thdimension.android; 3 | 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.graphics.Bitmap; 7 | import android.graphics.BitmapFactory; 8 | import android.graphics.Matrix; 9 | import android.media.ExifInterface; 10 | import android.net.Uri; 11 | import android.os.Build; 12 | import android.provider.MediaStore.Images.Media; 13 | import android.util.Log; 14 | 15 | import java.io.FileNotFoundException; 16 | import java.io.IOException; 17 | 18 | /** 19 | * Provides helper methods for image operations 20 | ***/ 21 | public class ImageUtils { 22 | 23 | private final static String TAG = ImageUtils.class.getSimpleName(); 24 | 25 | private static final String ERROR_URI_NULL = "Uri cannot be null"; 26 | 27 | /** 28 | * Scales the image depending upon the display density of the device. Maintains image aspect 29 | * ratio. 30 | *

31 | * When dealing with the bitmaps of bigger size, this method must be called from a non-UI 32 | * thread. 33 | **/ 34 | public static Bitmap scaleDownBitmap(Context ctx, Bitmap source, int newHeight) { 35 | final float densityMultiplier = Utils.getDensityMultiplier(ctx); 36 | 37 | // Log.v( TAG, "#scaleDownBitmap Original w: " + source.getWidth() + " h: " + 38 | // source.getHeight() ); 39 | 40 | int h = (int) (newHeight * densityMultiplier); 41 | int w = (int) (h * source.getWidth() / ((double) source.getHeight())); 42 | 43 | // Log.v( TAG, "#scaleDownBitmap Computed w: " + w + " h: " + h ); 44 | 45 | Bitmap photo = Bitmap.createScaledBitmap(source, w, h, true); 46 | 47 | // Log.v( TAG, "#scaleDownBitmap Final w: " + w + " h: " + h ); 48 | 49 | return photo; 50 | } 51 | 52 | /** 53 | * Scales the image independently of the screen density of the device. Maintains image aspect 54 | * ratio. 55 | *

56 | * When dealing with the bitmaps of bigger size, this method must be called from a non-UI 57 | * thread. 58 | */ 59 | public static Bitmap scaleBitmap(Context ctx, Bitmap source, int newHeight) { 60 | 61 | // Log.v( TAG, "#scaleDownBitmap Original w: " + source.getWidth() + " h: " + 62 | // source.getHeight() ); 63 | 64 | int w = (int) (newHeight * source.getWidth() / ((double) source.getHeight())); 65 | 66 | // Log.v( TAG, "#scaleDownBitmap Computed w: " + w + " h: " + newHeight ); 67 | 68 | Bitmap photo = Bitmap.createScaledBitmap(source, w, newHeight, true); 69 | 70 | // Log.v( TAG, "#scaleDownBitmap Final w: " + w + " h: " + newHeight ); 71 | 72 | return photo; 73 | } 74 | 75 | /** 76 | * Scales the image independently of the screen density of the device. Maintains image aspect 77 | * ratio. 78 | * 79 | * @param uri Uri of the source bitmap 80 | **/ 81 | public static Bitmap scaleDownBitmap(Context ctx, Uri uri, int newHeight) throws FileNotFoundException, IOException { 82 | Bitmap original = Media.getBitmap(ctx.getContentResolver(), uri); 83 | return scaleBitmap(ctx, original, newHeight); 84 | } 85 | 86 | /** 87 | * Scales the image independently of the screen density of the device. Maintains image aspect 88 | * ratio. 89 | * 90 | * @param uri Uri of the source bitmap 91 | **/ 92 | public static Uri scaleDownBitmapForUri(Context ctx, Uri uri, int newHeight) throws FileNotFoundException, IOException { 93 | 94 | if (uri == null) 95 | throw new NullPointerException(ERROR_URI_NULL); 96 | 97 | if (!MediaUtils.isMediaContentUri(uri)) 98 | return null; 99 | 100 | Bitmap original = Media.getBitmap(ctx.getContentResolver(), uri); 101 | Bitmap bmp = scaleBitmap(ctx, original, newHeight); 102 | 103 | Uri destUri = null; 104 | String uriStr = Utils.writeImageToMedia(ctx, bmp, "", ""); 105 | 106 | if (uriStr != null) { 107 | destUri = Uri.parse(uriStr); 108 | } 109 | 110 | return destUri; 111 | } 112 | 113 | /** 114 | * Gets the orientation of the image pointed to by the parameter uri 115 | * 116 | * @return Image orientation value corresponding to ExifInterface.ORIENTATION_*
117 | * Returns -1 if the row for the {@link android.net.Uri} is not found. 118 | **/ 119 | public static int getOrientation(Context context, Uri uri) { 120 | 121 | int invalidOrientation = -1; 122 | if (uri == null) { 123 | throw new NullPointerException(ERROR_URI_NULL); 124 | } 125 | 126 | if (!MediaUtils.isMediaContentUri(uri)) { 127 | return invalidOrientation; 128 | } 129 | 130 | String filePath = Utils.getPathForMediaUri(context, uri); 131 | ExifInterface exif = null; 132 | 133 | try { 134 | exif = new ExifInterface(filePath); 135 | } catch (IOException e) { 136 | e.printStackTrace(); 137 | } 138 | 139 | int orientation = invalidOrientation; 140 | if (exif != null) { 141 | orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, invalidOrientation); 142 | } 143 | 144 | return orientation; 145 | } 146 | 147 | /** 148 | * Rotate the image at the specified uri. For the rotation of the image the 149 | * {@link android.media.ExifInterface} data in the image will be used. 150 | * 151 | * @param uri Uri of the image to be rotated. 152 | **/ 153 | public static Uri rotateImage(Context context, Uri uri) throws FileNotFoundException, IOException { 154 | // rotate the image 155 | if (uri == null) { 156 | throw new NullPointerException(ERROR_URI_NULL); 157 | } 158 | 159 | if (!MediaUtils.isMediaContentUri(uri)) { 160 | return null; 161 | } 162 | 163 | int invalidOrientation = -1; 164 | byte[] data = Utils.getMediaData(context, uri); 165 | 166 | int orientation = getOrientation(context, uri); 167 | 168 | Uri newUri = null; 169 | 170 | try { 171 | 172 | Log.d(TAG, "#rotateImage Exif orientation: " + orientation); 173 | 174 | if (orientation != invalidOrientation) { 175 | Matrix matrix = new Matrix(); 176 | 177 | switch (orientation) { 178 | case ExifInterface.ORIENTATION_ROTATE_90: 179 | matrix.postRotate(90); 180 | break; 181 | case ExifInterface.ORIENTATION_ROTATE_180: 182 | matrix.postRotate(180); 183 | break; 184 | case ExifInterface.ORIENTATION_ROTATE_270: 185 | matrix.postRotate(270); 186 | break; 187 | } 188 | 189 | // set some options so the memory is manager properly 190 | BitmapFactory.Options options = new BitmapFactory.Options(); 191 | // options.inPreferredConfig = Bitmap.Config.RGB_565; // try to enable this if 192 | // OutOfMem issue still persists 193 | options.inPurgeable = true; 194 | options.inInputShareable = true; 195 | 196 | Bitmap original = BitmapFactory.decodeByteArray(data, 0, data.length, options); 197 | Bitmap rotatedBitmap = Bitmap.createBitmap(original, 0, 0, original.getWidth(), original.getHeight(), matrix, true); // rotating 198 | // bitmap 199 | String newUrl = Media.insertImage(((Activity) context).getContentResolver(), rotatedBitmap, "", ""); 200 | 201 | if (newUrl != null) { 202 | newUri = Uri.parse(newUrl); 203 | } 204 | } 205 | } catch (Exception e) { 206 | e.printStackTrace(); 207 | } 208 | 209 | return newUri; 210 | } 211 | 212 | /** 213 | * Get the size of parameter {@link Bitmap}. This maybe a heavy operation. 214 | * Prefer not calling from main thread of the activity. 215 | * 216 | * @param data 217 | * @return 218 | */ 219 | public static int sizeOf(Bitmap data) { 220 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) { 221 | return data.getRowBytes() * data.getHeight(); 222 | } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 223 | return data.getByteCount(); 224 | } else { 225 | return data.getAllocationByteCount(); 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/DateUtils.java: -------------------------------------------------------------------------------- 1 | 2 | package net.the4thdimension.android; 3 | 4 | import android.net.ParseException; 5 | 6 | import java.text.SimpleDateFormat; 7 | import java.util.Calendar; 8 | import java.util.Date; 9 | import java.util.Locale; 10 | import java.util.TimeZone; 11 | 12 | /*** 13 | * Provides helper methods for date utilities. 14 | * Yes, some times I write shit code. 15 | */ 16 | public class DateUtils { 17 | 18 | /*** 19 | * Converts ISO date string to UTC timezone equivalent. 20 | * 21 | * @param dateAndTime ISO formatted time string. 22 | */ 23 | public static String getUtcTime(String dateAndTime) { 24 | Date d = parseDate(dateAndTime); 25 | 26 | String format = "yyyy-MM-dd'T'HH:mm:ss'Z'"; 27 | SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault()); 28 | 29 | // Convert Local Time to UTC 30 | sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 31 | 32 | return sdf.format(d); 33 | } 34 | 35 | /**** 36 | * Parses date string and return a {@link java.util.Date} object 37 | * 38 | * @return The ISO formatted date object 39 | */ 40 | public static Date parseDate(String date) { 41 | 42 | if (date == null) { 43 | return null; 44 | } 45 | 46 | StringBuffer sbDate = new StringBuffer(); 47 | sbDate.append(date); 48 | String newDate = null; 49 | Date dateDT = null; 50 | 51 | try { 52 | newDate = sbDate.substring(0, 19).toString(); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | 57 | String rDate = newDate.replace("T", " "); 58 | String nDate = rDate.replaceAll("-", "/"); 59 | 60 | try { 61 | dateDT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault()).parse(nDate); 62 | // Log.v( TAG, "#parseDate dateDT: " + dateDT ); 63 | } catch (ParseException e) { 64 | e.printStackTrace(); 65 | } catch (Exception e) { 66 | e.printStackTrace(); 67 | } 68 | 69 | return dateDT; 70 | } 71 | 72 | /*** 73 | * Converts UTC time formatted as ISO to device local time. 74 | *

75 | *
76 | *
77 | * Sample usage 78 | *

79 | *

 80 |      *
 81 |      * {
 82 |      * 	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
 83 |      * 	d = toLocalTime("2014-10-08T09:46:04.455Z", sdf);
 84 |      * }
 85 |      * 
86 | * 87 | * @param utcDate 88 | * @param format 89 | * @return Date 90 | * @throws Exception 91 | */ 92 | public static Date toLocalTime(String utcDate, SimpleDateFormat sdf) throws Exception { 93 | 94 | // create a new Date object using 95 | // the timezone of the specified city 96 | sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 97 | Date localDate = sdf.parse(utcDate); 98 | 99 | sdf.setTimeZone(TimeZone.getDefault()); 100 | String dateFormateInUTC = sdf.format(localDate); 101 | 102 | return sdf.parse(dateFormateInUTC); 103 | } 104 | 105 | /** 106 | * Returns abbreviated (3 letters) day of the week. 107 | * 108 | * @param date ISO format date 109 | * @return The name of the day of the week 110 | */ 111 | public static String getDayOfWeekAbbreviated(String date) { 112 | Date dateDT = parseDate(date); 113 | 114 | if (dateDT == null) { 115 | return null; 116 | } 117 | 118 | // Get current date 119 | Calendar c = Calendar.getInstance(); 120 | // it is very important to 121 | // set the date of 122 | // the calendar. 123 | c.setTime(dateDT); 124 | int day = c.get(Calendar.DAY_OF_WEEK); 125 | 126 | String dayStr = null; 127 | 128 | switch (day) { 129 | 130 | case Calendar.SUNDAY: 131 | dayStr = "Sun"; 132 | break; 133 | 134 | case Calendar.MONDAY: 135 | dayStr = "Mon"; 136 | break; 137 | 138 | case Calendar.TUESDAY: 139 | dayStr = "Tue"; 140 | break; 141 | 142 | case Calendar.WEDNESDAY: 143 | dayStr = "Wed"; 144 | break; 145 | 146 | case Calendar.THURSDAY: 147 | dayStr = "Thu"; 148 | break; 149 | 150 | case Calendar.FRIDAY: 151 | dayStr = "Fri"; 152 | break; 153 | 154 | case Calendar.SATURDAY: 155 | dayStr = "Sat"; 156 | break; 157 | } 158 | 159 | return dayStr; 160 | } 161 | 162 | /*** 163 | * Gets the name of the month from the given date. 164 | * 165 | * @param date ISO format date 166 | * @return Returns the name of the month 167 | */ 168 | public static String getMonth(String date) { 169 | Date dateDT = parseDate(date); 170 | 171 | if (dateDT == null) { 172 | return null; 173 | } 174 | 175 | // Get current date 176 | Calendar c = Calendar.getInstance(); 177 | // it is very important to 178 | // set the date of 179 | // the calendar. 180 | c.setTime(dateDT); 181 | int day = c.get(Calendar.MONTH); 182 | 183 | String dayStr = null; 184 | 185 | switch (day) { 186 | 187 | case Calendar.JANUARY: 188 | dayStr = "January"; 189 | break; 190 | 191 | case Calendar.FEBRUARY: 192 | dayStr = "February"; 193 | break; 194 | 195 | case Calendar.MARCH: 196 | dayStr = "March"; 197 | break; 198 | 199 | case Calendar.APRIL: 200 | dayStr = "April"; 201 | break; 202 | 203 | case Calendar.MAY: 204 | dayStr = "May"; 205 | break; 206 | 207 | case Calendar.JUNE: 208 | dayStr = "June"; 209 | break; 210 | 211 | case Calendar.JULY: 212 | dayStr = "July"; 213 | break; 214 | 215 | case Calendar.AUGUST: 216 | dayStr = "August"; 217 | break; 218 | 219 | case Calendar.SEPTEMBER: 220 | dayStr = "September"; 221 | break; 222 | 223 | case Calendar.OCTOBER: 224 | dayStr = "October"; 225 | break; 226 | 227 | case Calendar.NOVEMBER: 228 | dayStr = "November"; 229 | break; 230 | 231 | case Calendar.DECEMBER: 232 | dayStr = "December"; 233 | break; 234 | } 235 | 236 | return dayStr; 237 | } 238 | 239 | /** 240 | * Gets abbreviated name of the month from the given date. 241 | * 242 | * @param date ISO format date 243 | * @return Returns the name of the month 244 | */ 245 | public static String getMonthAbbreviated(String date) { 246 | Date dateDT = parseDate(date); 247 | 248 | if (dateDT == null) { 249 | return null; 250 | } 251 | 252 | // Get current date 253 | Calendar c = Calendar.getInstance(); 254 | // it is very important to 255 | // set the date of 256 | // the calendar. 257 | c.setTime(dateDT); 258 | int day = c.get(Calendar.MONTH); 259 | 260 | String dayStr = null; 261 | 262 | switch (day) { 263 | 264 | case Calendar.JANUARY: 265 | dayStr = "Jan"; 266 | break; 267 | 268 | case Calendar.FEBRUARY: 269 | dayStr = "Feb"; 270 | break; 271 | 272 | case Calendar.MARCH: 273 | dayStr = "Mar"; 274 | break; 275 | 276 | case Calendar.APRIL: 277 | dayStr = "Apr"; 278 | break; 279 | 280 | case Calendar.MAY: 281 | dayStr = "May"; 282 | break; 283 | 284 | case Calendar.JUNE: 285 | dayStr = "Jun"; 286 | break; 287 | 288 | case Calendar.JULY: 289 | dayStr = "Jul"; 290 | break; 291 | 292 | case Calendar.AUGUST: 293 | dayStr = "Aug"; 294 | break; 295 | 296 | case Calendar.SEPTEMBER: 297 | dayStr = "Sep"; 298 | break; 299 | 300 | case Calendar.OCTOBER: 301 | dayStr = "Oct"; 302 | break; 303 | 304 | case Calendar.NOVEMBER: 305 | dayStr = "Nov"; 306 | break; 307 | 308 | case Calendar.DECEMBER: 309 | dayStr = "Dec"; 310 | break; 311 | } 312 | 313 | return dayStr; 314 | } 315 | 316 | /** 317 | * Gets a string TimeStamp phrase like 5 mins ago 318 | * yesterday, 3 days ago. 319 | * 320 | *
321 | *
322 | * 323 | * sample usage 324 | * 325 | * *
326 |      *
327 |      * {
328 |      * 	String timeStamp = getTimeStamp(originalDate);
329 |      *
330 |      * }
331 |      * 
332 | * 333 | * @param originalDate 334 | * @return convertedDate String 335 | * 336 | */ 337 | public static String getTimeStamp(Date originalDate){ 338 | 339 | String convertedDate = DateUtils.getRelativeTimeSpanString(originalDate.getTime(), 340 | new Date().getTime(), 341 | DateUtils.SECOND_IN_MILLIS).toString(); 342 | 343 | return convertedDate; 344 | } 345 | 346 | 347 | /** 348 | * Gets a string TimeStamp phrase like 5 mins ago 349 | * yesterday, 3 days ago. 350 | * 351 | *
352 | *
353 | * 354 | * sample usage 355 | * 356 | * *
357 |      *
358 |      * {
359 |      * 	String timeStamp = getTimeStamp(originalDate);
360 |      *
361 |      * }
362 |      * 
363 | * 364 | * @param originalDateTime time in miliseconds since epoch 365 | * @return convertedDate String 366 | * 367 | */ 368 | public static String getTimeStamp(Long originalDateTime) { 369 | 370 | String convertedDate = DateUtils.getRelativeTimeSpanString(originalDateTime, 371 | new Date().getTime(), 372 | DateUtils.SECOND_IN_MILLIS).toString(); 373 | 374 | return convertedDate; 375 | 376 | } 377 | 378 | } 379 | -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/MediaUtils.java: -------------------------------------------------------------------------------- 1 | package net.the4thdimension.android; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.ContentValues; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.pm.PackageManager; 9 | import android.content.pm.ResolveInfo; 10 | import android.database.Cursor; 11 | import android.net.Uri; 12 | import android.os.Parcelable; 13 | import android.provider.MediaStore; 14 | import android.provider.MediaStore.Video; 15 | import android.support.annotation.Nullable; 16 | import android.text.TextUtils; 17 | import android.util.Log; 18 | 19 | import java.io.File; 20 | import java.io.FileInputStream; 21 | import java.io.FileNotFoundException; 22 | import java.io.FileOutputStream; 23 | import java.io.IOException; 24 | import java.io.OutputStream; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | public class MediaUtils { 29 | 30 | private static final String TAG = MediaUtils.class.getSimpleName(); 31 | 32 | /** 33 | * Get runtime duration of media such as audio or video in milliseconds 34 | ****/ 35 | public static long getDuration(Context ctx, Uri mediaUri) { 36 | Cursor cur = ctx.getContentResolver().query(mediaUri, new String[]{Video.Media.DURATION}, null, null, null); 37 | long duration = -1; 38 | 39 | try { 40 | if (cur != null && cur.getCount() > 0) { 41 | while (cur.moveToNext()) { 42 | duration = cur.getLong(cur.getColumnIndex(Video.Media.DURATION)); 43 | 44 | if (duration == 0) 45 | Log.w(TAG, "#getMediaDuration The image size was found to be 0. Reason: UNKNOWN"); 46 | 47 | } // end while 48 | } else if (cur.getCount() == 0) { 49 | Log.e(TAG, "#getMediaDuration cur size is 0. File may not exist"); 50 | } else { 51 | Log.e(TAG, "#getMediaDuration cur is null"); 52 | } 53 | } finally { 54 | if (cur != null && !cur.isClosed()) { 55 | cur.close(); 56 | } 57 | } 58 | 59 | return duration; 60 | } 61 | 62 | /** 63 | * Checks if the parameter {@link android.net.Uri} is a Media content uri. 64 | ****/ 65 | public static boolean isMediaContentUri(Uri uri) { 66 | if (!uri.toString().contains("content://media/")) { 67 | Log.w(TAG, "#isContentUri The uri is not a media content uri"); 68 | return false; 69 | } else { 70 | return true; 71 | } 72 | } 73 | 74 | /** 75 | * Creates an intent to take a video from camera or gallery or any other application that can 76 | * handle the intent. 77 | * 78 | * @param ctx 79 | * @param savingUri 80 | * @param durationInSeconds 81 | * @return 82 | */ 83 | public static Intent createTakeVideoIntent(Activity ctx, Uri savingUri, int durationInSeconds) { 84 | 85 | if (savingUri == null) { 86 | throw new NullPointerException("Uri cannot be null"); 87 | } 88 | 89 | final List cameraIntents = new ArrayList(); 90 | final Intent captureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); 91 | final PackageManager packageManager = ctx.getPackageManager(); 92 | final List listCam = packageManager.queryIntentActivities(captureIntent, 0); 93 | for (ResolveInfo res : listCam) { 94 | final String packageName = res.activityInfo.packageName; 95 | final Intent intent = new Intent(captureIntent); 96 | intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); 97 | intent.setPackage(packageName); 98 | intent.putExtra(MediaStore.EXTRA_OUTPUT, savingUri); 99 | intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationInSeconds); 100 | cameraIntents.add(intent); 101 | } 102 | 103 | // Filesystem. 104 | final Intent galleryIntent = new Intent(); 105 | galleryIntent.setType("video/*"); 106 | galleryIntent.setAction(Intent.ACTION_GET_CONTENT); 107 | 108 | // Chooser of filesystem options. 109 | final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source"); 110 | 111 | // Add the camera options. 112 | chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{})); 113 | 114 | return chooserIntent; 115 | } 116 | 117 | /** 118 | * Creates a ACTION_IMAGE_CAPTURE photo & ACTION_GET_CONTENT intent. This intent will be 119 | * aggregation of intents required to take picture from Gallery and Camera at the minimum. The 120 | * intent will also be directed towards the apps that are capable of sourcing the image data. 121 | * For e.g. Dropbox, Astro file manager. 122 | * 123 | * @param savingUri Uri to store a high resolution image at. If the user takes the picture using the 124 | * camera the image will be stored at this uri. 125 | **/ 126 | public static Intent createTakePictureIntent(Activity ctx, Uri savingUri) { 127 | 128 | if (savingUri == null) { 129 | throw new NullPointerException("Uri cannot be null"); 130 | } 131 | 132 | final List cameraIntents = new ArrayList(); 133 | final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 134 | final PackageManager packageManager = ctx.getPackageManager(); 135 | final List listCam = packageManager.queryIntentActivities(captureIntent, 0); 136 | for (ResolveInfo res : listCam) { 137 | final String packageName = res.activityInfo.packageName; 138 | final Intent intent = new Intent(captureIntent); 139 | intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); 140 | intent.setPackage(packageName); 141 | intent.putExtra(MediaStore.EXTRA_OUTPUT, savingUri); 142 | cameraIntents.add(intent); 143 | } 144 | 145 | // Filesystem. 146 | final Intent galleryIntent = new Intent(); 147 | galleryIntent.setType("image/*"); 148 | galleryIntent.setAction(Intent.ACTION_GET_CONTENT); 149 | 150 | // Chooser of filesystem options. 151 | final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source"); 152 | 153 | // Add the camera options. 154 | chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{})); 155 | 156 | return chooserIntent; 157 | } 158 | 159 | @Nullable 160 | /** 161 | * Creates external content:// scheme uri to save the images at. The image saved at this 162 | * {@link android.net.Uri} will be visible via the gallery application on the device. 163 | **/ 164 | public static Uri createImageUri(Context ctx) throws IOException { 165 | 166 | if (ctx == null) { 167 | throw new NullPointerException("Context cannot be null"); 168 | } 169 | 170 | Uri imageUri = null; 171 | 172 | ContentValues values = new ContentValues(); 173 | values.put(MediaStore.MediaColumns.TITLE, ""); 174 | values.put(MediaStore.Images.ImageColumns.DESCRIPTION, ""); 175 | imageUri = ctx.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 176 | 177 | return imageUri; 178 | } 179 | 180 | @Nullable 181 | /** 182 | * Creates external content:// scheme uri to save the videos at. 183 | **/ 184 | public static Uri createVideoUri(Context ctx) throws IOException { 185 | 186 | if (ctx == null) { 187 | throw new NullPointerException("Context cannot be null"); 188 | } 189 | 190 | Uri imageUri = null; 191 | 192 | ContentValues values = new ContentValues(); 193 | values.put(MediaStore.MediaColumns.TITLE, ""); 194 | values.put(MediaStore.Images.ImageColumns.DESCRIPTION, ""); 195 | imageUri = ctx.getContentResolver().insert(Video.Media.EXTERNAL_CONTENT_URI, values); 196 | 197 | return imageUri; 198 | } 199 | 200 | @Nullable 201 | /** 202 | * Gets media type from the Uri. 203 | */ 204 | public static String getMediaType(Uri uri) { 205 | if (uri == null) { 206 | return null; 207 | } 208 | 209 | String uriStr = uri.toString(); 210 | 211 | if (uriStr.contains("video")) { 212 | return "video"; 213 | } else if (uriStr.contains("audio")) { 214 | return "audio"; 215 | } else if (uriStr.contains("image")) { 216 | return "image"; 217 | } else { 218 | return null; 219 | } 220 | } 221 | 222 | /** 223 | * Gets media file name. 224 | **/ 225 | public static String getMediaFileName(Context ctx, Uri mediaUri) { 226 | String colName = MediaStore.MediaColumns.DISPLAY_NAME; 227 | Cursor cur = ctx.getContentResolver().query(mediaUri, new String[]{colName}, null, null, null); 228 | String dispName = null; 229 | 230 | try { 231 | if (cur != null && cur.getCount() > 0) { 232 | while (cur.moveToNext()) { 233 | dispName = cur.getString(cur.getColumnIndex(colName)); 234 | 235 | // for unknown reason, the image size for image was found to 236 | // be 0 237 | // Log.v( TAG, "#getMediaFileName byte.size: " + size ); 238 | 239 | if (TextUtils.isEmpty(colName)) { 240 | Log.w(TAG, "#getMediaFileName The file name is blank or null. Reason: UNKNOWN"); 241 | } 242 | 243 | } // end while 244 | } else if (cur != null && cur.getCount() == 0) { 245 | Log.e(TAG, "#getMediaFileName File may not exist"); 246 | } else { 247 | Log.e(TAG, "#getMediaFileName cur is null"); 248 | } 249 | } finally { 250 | if (cur != null && !cur.isClosed()) { 251 | cur.close(); 252 | } 253 | } 254 | 255 | return dispName; 256 | } 257 | 258 | /** 259 | * Gets the size of the media resource pointed to by the parameter mediaUri. 260 | *

261 | * Known bug: for unknown reason, the image size for some images was found to be 0 262 | * 263 | * @param mediaUri uri to the media resource. For e.g. content://media/external/images/media/45490 or 264 | * content://media/external/video/media/45490 265 | * @return Size in bytes 266 | **/ 267 | public static long getMediaSize(Context context, Uri mediaUri) { 268 | Cursor cur = context.getContentResolver().query(mediaUri, new String[]{MediaStore.Images.Media.SIZE}, null, null, null); 269 | long size = -1; 270 | 271 | try { 272 | if (cur != null && cur.getCount() > 0) { 273 | while (cur.moveToNext()) { 274 | size = cur.getLong(cur.getColumnIndex(MediaStore.Images.Media.SIZE)); 275 | 276 | // for unknown reason, the image size for image was found to 277 | // be 0 278 | // Log.v( TAG, "#getSize byte.size: " + size ); 279 | 280 | if (size == 0) 281 | Log.w(TAG, "#getSize The media size was found to be 0. Reason: UNKNOWN"); 282 | 283 | } // end while 284 | } else if (cur.getCount() == 0) { 285 | Log.e(TAG, "#getMediaSize cur size is 0. File may not exist"); 286 | } else { 287 | Log.e(TAG, "#getMediaSize cur is null"); 288 | } 289 | } finally { 290 | if (cur != null && !cur.isClosed()) { 291 | cur.close(); 292 | } 293 | } 294 | 295 | return size; 296 | } 297 | 298 | @Nullable 299 | /** 300 | * Gets the media data from the one of the following media {@link android.content.ContentProvider} This method 301 | * should not be called from the main thread of the application. Calling this method may have 302 | * performance issues as this may allocate a huge memory array. 303 | *

    304 | *
  • {@link android.provider.MediaStore.Images.Media}
  • 305 | *
  • {@link android.provider.MediaStore.Audio.Media}
  • 306 | *
  • {@link android.provider.MediaStore.Video.Media}
  • 307 | *
308 | * 309 | * @param ctx Context object 310 | * @param uri Media content uri of the image, audio or video resource 311 | */ 312 | public static byte[] getMediaData(Context ctx, Uri uri) { 313 | if (uri == null) { 314 | throw new NullPointerException("Uri cannot be null"); 315 | } 316 | 317 | Cursor cur = ctx.getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null); 318 | byte[] data = null; 319 | 320 | try { 321 | if (cur != null && cur.getCount() > 0) { 322 | if (cur.moveToNext()) { 323 | String path = cur.getString(cur.getColumnIndex(MediaStore.Images.Media.DATA)); 324 | 325 | try { 326 | File f = new File(path); 327 | FileInputStream fis = new FileInputStream(f); 328 | data = Utils.readStreamToBytes(fis); 329 | } catch (FileNotFoundException e) { 330 | e.printStackTrace(); 331 | } catch (Exception e) { 332 | e.printStackTrace(); 333 | } 334 | 335 | // Log.v( TAG, "#getVideoData byte.size: " + data.length ); 336 | } // end while 337 | } else 338 | Log.e(TAG, "#getMediaData cur is null or blank"); 339 | } finally { 340 | if (cur != null && !cur.isClosed()) { 341 | cur.close(); 342 | } 343 | } 344 | 345 | return data; 346 | } 347 | 348 | /** 349 | * Returns true if the mime type is a standard image mime type 350 | */ 351 | public static boolean isImage(String mimeType) { 352 | // TODO: apply regex patter for checking the MIME type 353 | if (mimeType != null) { 354 | if (mimeType.startsWith("image/")) 355 | return true; 356 | else 357 | return false; 358 | } else 359 | return false; 360 | } 361 | 362 | /** 363 | * Returns true if the mime type is a standard audio mime type 364 | */ 365 | public static boolean isAudio(String mimeType) { 366 | // TODO: apply regex patter for checking the MIME type 367 | if (mimeType != null) { 368 | if (mimeType.startsWith("audio/")) 369 | return true; 370 | else 371 | return false; 372 | } else 373 | return false; 374 | } 375 | 376 | /** 377 | * Returns true if the mime type is a standard video mime type 378 | */ 379 | public static boolean isVideo(String mimeType) { 380 | // TODO: apply regex patter for checking the MIME type 381 | if (mimeType != null) { 382 | if (mimeType.startsWith("video/")) 383 | return true; 384 | else 385 | return false; 386 | } else { 387 | return false; 388 | } 389 | } 390 | 391 | /** 392 | * Identifies if the content represented by the parameter mimeType is media. Image, Audio and 393 | * Video is treated as media by this method. You can refer to standard MIME type here. Standard MIME 395 | * types. 396 | * 397 | * @param mimeType standard MIME type of the data. 398 | */ 399 | public static boolean isMedia(String mimeType) { 400 | boolean isMedia = false; 401 | 402 | if (mimeType != null) { 403 | if (mimeType.startsWith("image/") || mimeType.startsWith("video/") || mimeType.startsWith("audio/")) { 404 | isMedia = true; 405 | } 406 | } else { 407 | isMedia = false; 408 | } 409 | 410 | return isMedia; 411 | } 412 | 413 | /** 414 | * Get the type of the media. Audio, Video or Image. 415 | * 416 | * @return Lower case string for one of above listed media type 417 | */ 418 | public static String getMediaType(String contentType) { 419 | if (isMedia(contentType)) { 420 | if (isVideo(contentType)) 421 | return "video"; 422 | else if (isAudio(contentType)) 423 | return "audio"; 424 | else if (isImage(contentType)) 425 | return "image"; 426 | else 427 | return null; 428 | } else { 429 | return null; 430 | } 431 | } 432 | 433 | /** 434 | * Writes the given image to the external storage of the device. If external storage is not 435 | * available, the image is written to the application private directory 436 | * 437 | * @return Path of the image file that has been written. 438 | **/ 439 | public static String writeImage(Context ctx, byte[] imageData) { 440 | 441 | final String FILE_NAME = "photograph.jpeg"; 442 | File dir = null; 443 | String filePath = null; 444 | OutputStream imageFileOS; 445 | 446 | dir = Utils.getStorageDirectory(ctx, null); 447 | 448 | // dir.mkdirs(); 449 | File f = new File(dir, FILE_NAME); 450 | 451 | // File f = getFile( FILE_NAME ); 452 | 453 | try { 454 | imageFileOS = new FileOutputStream(f); 455 | imageFileOS.write(imageData); 456 | imageFileOS.flush(); 457 | imageFileOS.close(); 458 | } catch (FileNotFoundException e) { 459 | e.printStackTrace(); 460 | } catch (IOException e) { 461 | e.printStackTrace(); 462 | } catch (Exception e) { 463 | e.printStackTrace(); 464 | } 465 | 466 | filePath = f.getAbsolutePath(); 467 | 468 | return filePath; 469 | } 470 | } 471 | -------------------------------------------------------------------------------- /Utils/app/src/main/java/net/the4thdimension/android/Utils.java: -------------------------------------------------------------------------------- 1 | 2 | package net.the4thdimension.android; 3 | 4 | import android.app.Activity; 5 | import android.app.ActivityManager; 6 | import android.app.ActivityManager.RunningServiceInfo; 7 | import android.app.AlertDialog; 8 | import android.app.ProgressDialog; 9 | import android.content.ComponentName; 10 | import android.content.ContentValues; 11 | import android.content.Context; 12 | import android.content.DialogInterface; 13 | import android.content.Intent; 14 | import android.content.pm.ApplicationInfo; 15 | import android.content.pm.PackageManager; 16 | import android.content.pm.PackageManager.NameNotFoundException; 17 | import android.content.pm.ResolveInfo; 18 | import android.database.Cursor; 19 | import android.database.sqlite.SQLiteDatabase; 20 | import android.database.sqlite.SQLiteException; 21 | import android.graphics.Bitmap; 22 | import android.graphics.Bitmap.Config; 23 | import android.graphics.BitmapFactory; 24 | import android.graphics.Canvas; 25 | import android.graphics.Color; 26 | import android.graphics.Paint; 27 | import android.graphics.PorterDuff.Mode; 28 | import android.graphics.PorterDuffXfermode; 29 | import android.graphics.Rect; 30 | import android.graphics.Typeface; 31 | import android.graphics.drawable.BitmapDrawable; 32 | import android.graphics.drawable.Drawable; 33 | import android.location.Location; 34 | import android.location.LocationManager; 35 | import android.location.LocationProvider; 36 | import android.net.ConnectivityManager; 37 | import android.net.NetworkInfo; 38 | import android.net.ParseException; 39 | import android.net.Uri; 40 | import android.os.Build; 41 | import android.os.Environment; 42 | import android.os.Parcelable; 43 | import android.provider.MediaStore; 44 | import android.provider.MediaStore.Images.ImageColumns; 45 | import android.provider.MediaStore.Images.Media; 46 | import android.provider.MediaStore.MediaColumns; 47 | import android.provider.MediaStore.Video; 48 | import android.support.annotation.NonNull; 49 | import android.support.annotation.Nullable; 50 | import android.support.annotation.StringRes; 51 | import android.telephony.TelephonyManager; 52 | import android.text.Spannable; 53 | import android.text.SpannableStringBuilder; 54 | import android.text.TextUtils; 55 | import android.text.style.StyleSpan; 56 | import android.util.Base64; 57 | import android.util.Log; 58 | import android.view.inputmethod.InputMethodManager; 59 | import android.widget.TextView; 60 | import android.widget.Toast; 61 | 62 | import org.json.JSONArray; 63 | import org.json.JSONException; 64 | 65 | import java.io.BufferedReader; 66 | import java.io.ByteArrayInputStream; 67 | import java.io.ByteArrayOutputStream; 68 | import java.io.File; 69 | import java.io.FileInputStream; 70 | import java.io.FileNotFoundException; 71 | import java.io.FileOutputStream; 72 | import java.io.IOException; 73 | import java.io.InputStream; 74 | import java.io.InputStreamReader; 75 | import java.io.OutputStream; 76 | import java.lang.reflect.InvocationTargetException; 77 | import java.lang.reflect.Method; 78 | import java.net.MalformedURLException; 79 | import java.net.URISyntaxException; 80 | import java.net.URL; 81 | import java.security.MessageDigest; 82 | import java.security.NoSuchAlgorithmException; 83 | import java.text.DecimalFormat; 84 | import java.text.SimpleDateFormat; 85 | import java.util.ArrayList; 86 | import java.util.Calendar; 87 | import java.util.Date; 88 | import java.util.GregorianCalendar; 89 | import java.util.List; 90 | import java.util.Random; 91 | import java.util.TimeZone; 92 | import java.util.regex.Matcher; 93 | import java.util.regex.Pattern; 94 | 95 | 96 | /** 97 | * Provides convenience methods and abstractions to some tasks in Android 98 | *

99 | *
100 | *
101 | * 102 | * @author Jay 103 | */ 104 | public class Utils { 105 | 106 | private static final String TAG = Utils.class.getSimpleName(); 107 | 108 | static ProgressDialog mProgressDialog; 109 | 110 | /** 111 | * Shows a long time duration toast message. 112 | * 113 | * @param msg Message to be show in the toast. 114 | * @return Toast object just shown 115 | **/ 116 | public static Toast showToast(Context ctx, CharSequence msg) { 117 | return showToast(ctx, msg, Toast.LENGTH_LONG); 118 | } 119 | 120 | /** 121 | * Shows the message passed in the parameter in the Toast. 122 | * 123 | * @param msg Message to be show in the toast. 124 | * @param duration Duration in milliseconds for which the toast should be shown 125 | * @return Toast object just shown 126 | **/ 127 | public static Toast showToast(Context ctx, CharSequence msg, int duration) { 128 | Toast toast = Toast.makeText(ctx, msg, Toast.LENGTH_SHORT); 129 | toast.setDuration(duration); 130 | toast.show(); 131 | return toast; 132 | } 133 | 134 | /** 135 | * Checks if the Internet connection is available. 136 | * 137 | * @return Returns true if the Internet connection is available. False otherwise. 138 | **/ 139 | public static boolean isInternetAvailable(Context ctx) { 140 | // using received context (typically activity) to get SystemService causes memory link as this holds strong reference to that activity. 141 | // use application level context instead, which is available until the app dies. 142 | ConnectivityManager connectivityManager = (ConnectivityManager) ctx.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); 143 | 144 | NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); 145 | 146 | // if network is NOT available networkInfo will be null 147 | // otherwise check if we are connected 148 | if (networkInfo != null && networkInfo.isConnected()) { 149 | return true; 150 | } 151 | 152 | return false; 153 | } 154 | 155 | /** 156 | * Checks if the SD Card is mounted on the device. 157 | **/ 158 | public static boolean isSdCardMounted() { 159 | String status = Environment.getExternalStorageState(); 160 | 161 | if (status != null && status.equals(Environment.MEDIA_MOUNTED)) { 162 | return true; 163 | } 164 | 165 | return false; 166 | } 167 | 168 | /** 169 | * Shows an alert dialog with the OK button. When the user presses OK button, the dialog 170 | * dismisses. 171 | **/ 172 | public static void showAlertDialog(Context context, @StringRes int titleResId, @StringRes int bodyResId) { 173 | showAlertDialog(context, context.getString(titleResId), 174 | context.getString(bodyResId), null); 175 | } 176 | 177 | /** 178 | * Shows an alert dialog with the OK button. When the user presses OK button, the dialog 179 | * dismisses. 180 | **/ 181 | public static void showAlertDialog(Context context, String title, String body) { 182 | showAlertDialog(context, title, body, null); 183 | } 184 | 185 | /** 186 | * Shows an alert dialog with OK button 187 | **/ 188 | public static void showAlertDialog(Context context, String title, String body, DialogInterface.OnClickListener okListener) { 189 | 190 | if (okListener == null) { 191 | okListener = new DialogInterface.OnClickListener() { 192 | 193 | public void onClick(DialogInterface dialog, int which) { 194 | dialog.cancel(); 195 | } 196 | }; 197 | } 198 | 199 | AlertDialog.Builder builder = new AlertDialog.Builder(context) 200 | .setMessage(body).setPositiveButton("OK", okListener); 201 | 202 | if (!TextUtils.isEmpty(title)) { 203 | builder.setTitle(title); 204 | } 205 | 206 | builder.show(); 207 | } 208 | 209 | /** 210 | * Serializes the Bitmap to Base64 211 | * 212 | * @return Base64 string value of a {@linkplain android.graphics.Bitmap} passed in as a parameter 213 | * @throws NullPointerException If the parameter bitmap is null. 214 | **/ 215 | public static String toBase64(Bitmap bitmap) { 216 | 217 | if (bitmap == null) { 218 | throw new NullPointerException("Bitmap cannot be null"); 219 | } 220 | 221 | String base64Bitmap = null; 222 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 223 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); 224 | byte[] imageBitmap = stream.toByteArray(); 225 | base64Bitmap = Base64.encodeToString(imageBitmap, Base64.DEFAULT); 226 | 227 | return base64Bitmap; 228 | } 229 | 230 | /** 231 | * Converts the passed in drawable to Bitmap representation 232 | * 233 | * @throws NullPointerException If the parameter drawable is null. 234 | **/ 235 | public static Bitmap drawableToBitmap(Drawable drawable) { 236 | 237 | if (drawable == null) { 238 | throw new NullPointerException("Drawable to convert should NOT be null"); 239 | } 240 | 241 | if (drawable instanceof BitmapDrawable) { 242 | return ((BitmapDrawable) drawable).getBitmap(); 243 | } 244 | 245 | if (drawable.getIntrinsicWidth() <= 0 && drawable.getIntrinsicHeight() <= 0) { 246 | return null; 247 | } 248 | 249 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888); 250 | Canvas canvas = new Canvas(bitmap); 251 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 252 | drawable.draw(canvas); 253 | 254 | return bitmap; 255 | } 256 | 257 | /** 258 | * Converts the given bitmap to {@linkplain java.io.InputStream}. 259 | * 260 | * @throws NullPointerException If the parameter bitmap is null. 261 | **/ 262 | public static InputStream bitmapToInputStream(Bitmap bitmap) throws NullPointerException { 263 | 264 | if (bitmap == null) { 265 | throw new NullPointerException("Bitmap cannot be null"); 266 | } 267 | 268 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 269 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); 270 | InputStream inputstream = new ByteArrayInputStream(baos.toByteArray()); 271 | 272 | return inputstream; 273 | } 274 | 275 | /** 276 | * Shows a progress dialog with a spinning animation in it. This method must preferably called 277 | * from a UI thread. 278 | * 279 | * @param ctx Activity context 280 | * @param title Title of the progress dialog 281 | * @param body Body/Message to be shown in the progress dialog 282 | * @param isCancellable True if the dialog can be cancelled on back button press, false otherwise 283 | **/ 284 | public static void showProgressDialog(Context ctx, String title, String body, boolean isCancellable) { 285 | showProgressDialog(ctx, title, body, null, isCancellable); 286 | } 287 | 288 | /** 289 | * Shows a progress dialog with a spinning animation in it. This method must preferably called 290 | * from a UI thread. 291 | * 292 | * @param ctx Activity context 293 | * @param title Title of the progress dialog 294 | * @param body Body/Message to be shown in the progress dialog 295 | * @param icon Icon to show in the progress dialog. It can be null. 296 | * @param isCancellable True if the dialog can be cancelled on back button press, false otherwise 297 | **/ 298 | public static void showProgressDialog(Context ctx, String title, String body, Drawable icon, boolean isCancellable) { 299 | 300 | if (ctx instanceof Activity) { 301 | if (!((Activity) ctx).isFinishing()) { 302 | mProgressDialog = ProgressDialog.show(ctx, title, body, true); 303 | mProgressDialog.setIcon(icon); 304 | mProgressDialog.setCancelable(isCancellable); 305 | } 306 | } 307 | } 308 | 309 | /** 310 | * Check if the {@link android.app.ProgressDialog} is visible in the UI. 311 | **/ 312 | public static boolean isProgressDialogVisible() { 313 | return (mProgressDialog != null); 314 | } 315 | 316 | /** 317 | * Dismiss the progress dialog if it is visible. 318 | **/ 319 | public static void dismissProgressDialog() { 320 | 321 | if (mProgressDialog != null) { 322 | mProgressDialog.dismiss(); 323 | } 324 | 325 | mProgressDialog = null; 326 | } 327 | 328 | /** 329 | * Gives the device independent constant which can be used for scaling images, manipulating view 330 | * sizes and changing dimension and display pixels etc. 331 | **/ 332 | public static float getDensityMultiplier(Context context) { 333 | return context.getResources().getDisplayMetrics().density; 334 | } 335 | 336 | /** 337 | * This method converts device specific pixels to density independent pixels. 338 | * 339 | * @param px A value in px (pixels) unit. Which we need to convert into db 340 | * @param context Context to get resources and device specific display metrics 341 | * @return A int value to represent dp equivalent to px value 342 | */ 343 | public static int getDip(int px, Context context) { 344 | final float scale = context.getResources().getDisplayMetrics().density; 345 | return (int) (px * scale + 0.5f); 346 | } 347 | 348 | /** 349 | * Creates a confirmation dialog with Yes-No Button. By default the buttons just dismiss the 350 | * dialog. 351 | * 352 | * @param ctx 353 | * @param message Message to be shown in the dialog. 354 | * @param yesListener Yes click handler 355 | * @param noListener 356 | **/ 357 | public static void showConfirmDialog(Context ctx, String message, DialogInterface.OnClickListener yesListener, DialogInterface.OnClickListener noListener) { 358 | showConfirmDialog(ctx, message, yesListener, noListener, "Yes", "No"); 359 | } 360 | 361 | /** 362 | * Creates a confirmation dialog with Yes-No Button. By default the buttons just dismiss the 363 | * dialog. 364 | * 365 | * @param ctx 366 | * @param message Message to be shown in the dialog. 367 | * @param yesListener Yes click handler 368 | * @param noListener 369 | * @param yesLabel Label for yes button 370 | * @param noLabel Label for no button 371 | **/ 372 | public static void showConfirmDialog(Context ctx, String message, DialogInterface.OnClickListener yesListener, DialogInterface.OnClickListener noListener, String yesLabel, String noLabel) { 373 | 374 | AlertDialog.Builder builder = new AlertDialog.Builder(ctx); 375 | 376 | if (yesListener == null) { 377 | yesListener = new DialogInterface.OnClickListener() { 378 | 379 | @Override 380 | public void onClick(DialogInterface dialog, int which) { 381 | dialog.dismiss(); 382 | } 383 | }; 384 | } 385 | 386 | if (noListener == null) { 387 | noListener = new DialogInterface.OnClickListener() { 388 | 389 | public void onClick(DialogInterface dialog, int which) { 390 | dialog.dismiss(); 391 | } 392 | }; 393 | } 394 | 395 | builder.setMessage(message).setPositiveButton(yesLabel, yesListener).setNegativeButton(noLabel, noListener).show(); 396 | } 397 | 398 | /** 399 | * Creates a confirmation dialog that show a pop-up with button labeled as parameters labels. 400 | * 401 | * @param ctx {@link android.app.Activity} {@link android.content.Context} 402 | * @param message Message to be shown in the dialog. 403 | * @param dialogClickListener 404 | * @param positiveBtnLabel For e.g. "Yes" 405 | * @param negativeBtnLabel For e.g. "No" 406 | **/ 407 | public static void showDialog(Context ctx, String message, String positiveBtnLabel, String negativeBtnLabel, DialogInterface.OnClickListener dialogClickListener) { 408 | 409 | if (dialogClickListener == null) { 410 | throw new NullPointerException("Action listener cannot be null"); 411 | } 412 | 413 | AlertDialog.Builder builder = new AlertDialog.Builder(ctx); 414 | 415 | builder.setMessage(message).setPositiveButton(positiveBtnLabel, dialogClickListener).setNegativeButton(negativeBtnLabel, dialogClickListener).show(); 416 | } 417 | 418 | /** 419 | * Gets the version name of the application. For e.g. 1.9.3 420 | **/ 421 | public static String getApplicationVersionNumber(Context context) { 422 | 423 | String versionName = null; 424 | 425 | if (context == null) { 426 | return versionName; 427 | } 428 | 429 | try { 430 | versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; 431 | } catch (NameNotFoundException e) { 432 | e.printStackTrace(); 433 | } 434 | 435 | return versionName; 436 | } 437 | 438 | /** 439 | * Gets the version code of the application. For e.g. Maverick Meerkat or 2013050301 440 | **/ 441 | public static int getApplicationVersionCode(Context ctx) { 442 | 443 | int versionCode = 0; 444 | 445 | try { 446 | versionCode = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0).versionCode; 447 | } catch (NameNotFoundException e) { 448 | e.printStackTrace(); 449 | } 450 | 451 | return versionCode; 452 | } 453 | 454 | /** 455 | * Gets the version number of the Android OS For e.g. 2.3.4 or 4.1.2 456 | **/ 457 | public static String getOsVersion() { 458 | return Build.VERSION.RELEASE; 459 | } 460 | 461 | /** 462 | * Checks if the service with the given name is currently running on the device. 463 | * 464 | * @param serviceName Fully qualified name of the server.
465 | * For e.g. nl.changer.myservice.name 466 | **/ 467 | public static boolean isServiceRunning(Context ctx, String serviceName) { 468 | 469 | if (serviceName == null) { 470 | throw new NullPointerException("Service name cannot be null"); 471 | } 472 | 473 | // use application level context to avoid unnecessary leaks. 474 | ActivityManager manager = (ActivityManager) ctx.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE); 475 | for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 476 | if (service.service.getClassName().equals(serviceName)) { 477 | return true; 478 | } 479 | } 480 | 481 | return false; 482 | } 483 | 484 | /** 485 | * Gets the device unique id called IMEI. Sometimes, this returns 00000000000000000 for the 486 | * rooted devices. 487 | **/ 488 | public static String getDeviceImei(Context ctx) { 489 | // use application level context to avoid unnecessary leaks. 490 | TelephonyManager telephonyManager = (TelephonyManager) ctx.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); 491 | return telephonyManager.getDeviceId(); 492 | } 493 | 494 | /** 495 | * Shares an application over the social network like Facebook, Twitter etc. 496 | * 497 | * @param sharingMsg Message to be pre-populated when the 3rd party app dialog opens up. 498 | * @param emailSubject Message that shows up as a subject while sharing through email. 499 | * @param title Title of the sharing options prompt. For e.g. "Share via" or "Share using" 500 | **/ 501 | public static void share(Context ctx, String sharingMsg, String emailSubject, String title) { 502 | Intent sharingIntent = new Intent(Intent.ACTION_SEND); 503 | 504 | sharingIntent.setType("text/plain"); 505 | sharingIntent.putExtra(Intent.EXTRA_TEXT, sharingMsg); 506 | sharingIntent.putExtra(Intent.EXTRA_SUBJECT, emailSubject); 507 | 508 | ctx.startActivity(Intent.createChooser(sharingIntent, title)); 509 | } 510 | 511 | /** 512 | * Checks the type of data connection that is currently available on the device. 513 | * 514 | * @return ConnectivityManager.TYPE_* as a type of internet connection on the 515 | * device. Returns -1 in case of error or none of 516 | * ConnectivityManager.TYPE_* is found. 517 | **/ 518 | public static int getDataConnectionType(Context ctx) { 519 | 520 | // use application level context to avoid unnecessary leaks. 521 | ConnectivityManager connectivityManager = (ConnectivityManager) ctx.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); 522 | 523 | if (connectivityManager != null && connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) != null) { 524 | if (connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected()) { 525 | return ConnectivityManager.TYPE_MOBILE; 526 | } else if (connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()) { 527 | return ConnectivityManager.TYPE_WIFI; 528 | } else 529 | return -1; 530 | } else 531 | return -1; 532 | } 533 | 534 | /** 535 | * Checks if the input parameter is a valid email. 536 | * 537 | * @param email 538 | * @return 539 | */ 540 | public static boolean isValidEmail(String email) { 541 | 542 | if (email == null) { 543 | return false; 544 | } 545 | 546 | final String emailPattern = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; 547 | Matcher matcher; 548 | Pattern pattern = Pattern.compile(emailPattern); 549 | 550 | matcher = pattern.matcher(email); 551 | 552 | if (matcher != null) { 553 | return matcher.matches(); 554 | } else { 555 | return false; 556 | } 557 | } 558 | 559 | @Nullable 560 | /** 561 | * Capitalizes each word in the string. 562 | * @param string 563 | * @return 564 | */ 565 | public static String capitalizeString(String string) { 566 | 567 | if (string == null) { 568 | return null; 569 | } 570 | 571 | char[] chars = string.toLowerCase().toCharArray(); 572 | boolean found = false; 573 | for (int i = 0; i < chars.length; i++) { 574 | if (!found && Character.isLetter(chars[i])) { 575 | chars[i] = Character.toUpperCase(chars[i]); 576 | found = true; 577 | } else if (Character.isWhitespace(chars[i]) || chars[i] == '.' || chars[i] == '\'') { // You 578 | // can add other 579 | // chars here 580 | found = false; 581 | } 582 | } // end for 583 | 584 | return String.valueOf(chars); 585 | } 586 | 587 | /** 588 | * Checks if the DB with the given name is present on the device. 589 | * 590 | * @param packageName 591 | * @param dbName 592 | * @return 593 | */ 594 | public static boolean isDatabasePresent(String packageName, String dbName) { 595 | SQLiteDatabase sqLiteDatabase = null; 596 | try { 597 | sqLiteDatabase = SQLiteDatabase.openDatabase("/data/data/" + packageName + "/databases/" + dbName, null, SQLiteDatabase.OPEN_READONLY); 598 | sqLiteDatabase.close(); 599 | } catch (SQLiteException e) { 600 | // database doesn't exist yet. 601 | e.printStackTrace(); 602 | Log.e(TAG, "The database does not exist." + e.getMessage()); 603 | } catch (Exception e) { 604 | e.printStackTrace(); 605 | Log.e(TAG, "Exception " + e.getMessage()); 606 | } 607 | 608 | return (sqLiteDatabase != null); 609 | } 610 | 611 | /** 612 | * Get the file path from the Media Content Uri for video, audio or images. 613 | * 614 | * @param mediaContentUri Media content Uri. 615 | **/ 616 | public static String getPathForMediaUri(Context context, Uri mediaContentUri) { 617 | 618 | Cursor cur = null; 619 | String path = null; 620 | 621 | try { 622 | String[] projection = {MediaColumns.DATA}; 623 | cur = context.getContentResolver().query(mediaContentUri, projection, null, null, null); 624 | 625 | if (cur != null && cur.getCount() != 0) { 626 | cur.moveToFirst(); 627 | path = cur.getString(cur.getColumnIndexOrThrow(MediaColumns.DATA)); 628 | } 629 | 630 | // Log.v( TAG, "#getRealPathFromURI Path: " + path ); 631 | } catch (Exception e) { 632 | e.printStackTrace(); 633 | } finally { 634 | if (cur != null && !cur.isClosed()) 635 | cur.close(); 636 | } 637 | 638 | return path; 639 | } 640 | 641 | public static ArrayList toStringArray(JSONArray jsonArr) { 642 | 643 | if (jsonArr == null || jsonArr.length() == 0) { 644 | return null; 645 | } 646 | 647 | ArrayList stringArray = new ArrayList(); 648 | 649 | for (int i = 0, count = jsonArr.length(); i < count; i++) { 650 | try { 651 | String str = jsonArr.getString(i); 652 | stringArray.add(str); 653 | } catch (JSONException e) { 654 | e.printStackTrace(); 655 | } catch (Exception e) { 656 | e.printStackTrace(); 657 | } 658 | } 659 | 660 | return stringArray; 661 | } 662 | 663 | /** 664 | * Convert a given list of {@link String} into a {@link org.json.JSONArray} 665 | **/ 666 | public static JSONArray toJSONArray(ArrayList stringArr) { 667 | JSONArray jsonArr = new JSONArray(); 668 | 669 | for (int i = 0; i < stringArr.size(); i++) { 670 | String value = stringArr.get(i); 671 | jsonArr.put(value); 672 | } 673 | 674 | return jsonArr; 675 | } 676 | 677 | /** 678 | * Gets the data storage directory(pictures dir) for the device. If the external storage is not 679 | * available, this returns the reserved application data storage directory. SD Card storage will 680 | * be preferred over internal storage. 681 | * 682 | * @param dirName if the directory name is specified, it is created inside the DIRECTORY_PICTURES 683 | * directory. 684 | * @return Data storage directory on the device. Maybe be a directory on SD Card or internal 685 | * storage of the device. 686 | **/ 687 | public static File getStorageDirectory(Context ctx, String dirName) { 688 | 689 | if (TextUtils.isEmpty(dirName)) { 690 | dirName = "atemp"; 691 | } 692 | 693 | File f = null; 694 | 695 | String state = Environment.getExternalStorageState(); 696 | 697 | if (Environment.MEDIA_MOUNTED.equals(state)) { 698 | f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/" + dirName); 699 | } else { 700 | // media is removed, unmounted etc 701 | // Store image in 702 | // /data/data//cache/atemp/photograph.jpeg 703 | f = new File(ctx.getCacheDir() + "/" + dirName); 704 | } 705 | 706 | if (!f.exists()) { 707 | f.mkdirs(); 708 | } 709 | 710 | return f; 711 | } 712 | 713 | /** 714 | * Given a file name, this method creates a {@link java.io.File} on best chosen device storage and 715 | * returns the file object. You can get the file path using {@link java.io.File#getAbsolutePath()} 716 | **/ 717 | public static File getFile(Context ctx, String fileName) { 718 | File dir = getStorageDirectory(ctx, null); 719 | File f = new File(dir, fileName); 720 | return f; 721 | } 722 | 723 | /** 724 | * @return Path of the image file that has been written. 725 | * @deprecated Use {@link MediaUtils#writeImage(Context, byte[])} 726 | * Writes the given image to the external storage of the device. If external storage is not 727 | * available, the image is written to the application private directory 728 | **/ 729 | public static String writeImage(Context ctx, byte[] imageData) { 730 | 731 | final String FILE_NAME = "photograph.jpeg"; 732 | File dir = null; 733 | String filePath = null; 734 | OutputStream imageFileOS; 735 | 736 | dir = getStorageDirectory(ctx, null); 737 | File f = new File(dir, FILE_NAME); 738 | 739 | try { 740 | imageFileOS = new FileOutputStream(f); 741 | imageFileOS.write(imageData); 742 | imageFileOS.flush(); 743 | imageFileOS.close(); 744 | } catch (FileNotFoundException e) { 745 | e.printStackTrace(); 746 | } catch (IOException e) { 747 | e.printStackTrace(); 748 | } catch (Exception e) { 749 | e.printStackTrace(); 750 | } 751 | 752 | filePath = f.getAbsolutePath(); 753 | 754 | return filePath; 755 | } 756 | 757 | /** 758 | * Inserts an image into {@link android.provider.MediaStore.Images.Media} content provider of the device. 759 | * 760 | * @return The media content Uri to the newly created image, or null if the image failed to be 761 | * stored for any reason. 762 | **/ 763 | public static String writeImageToMedia(Context ctx, Bitmap image, String title, String description) { 764 | // TODO: move to MediaUtils 765 | if (ctx == null) { 766 | throw new NullPointerException("Context cannot be null"); 767 | } 768 | 769 | return Media.insertImage(ctx.getContentResolver(), image, title, description); 770 | } 771 | 772 | /** 773 | * Gets the name of the application that has been defined in AndroidManifest.xml 774 | * 775 | * @throws android.content.pm.PackageManager.NameNotFoundException 776 | **/ 777 | public static String getApplicationName(Context ctx) throws NameNotFoundException { 778 | 779 | if (ctx == null) { 780 | throw new NullPointerException("Context cannot be null"); 781 | } 782 | 783 | final PackageManager packageMgr = ctx.getPackageManager(); 784 | ApplicationInfo appInfo = null; 785 | 786 | try { 787 | appInfo = packageMgr.getApplicationInfo(ctx.getPackageName(), PackageManager.SIGNATURE_MATCH); 788 | } catch (final NameNotFoundException e) { 789 | throw new NameNotFoundException(e.getMessage()); 790 | } 791 | 792 | final String applicationName = (String) (appInfo != null ? packageMgr.getApplicationLabel(appInfo) : "UNKNOWN"); 793 | 794 | return applicationName; 795 | } 796 | 797 | /** 798 | * Returns the URL without the query string 799 | **/ 800 | public static URL getPathFromUrl(URL url) { 801 | 802 | if (url != null) { 803 | String urlStr = url.toString(); 804 | String urlWithoutQueryString = urlStr.split("\\?")[0]; 805 | try { 806 | return new URL(urlWithoutQueryString); 807 | } catch (MalformedURLException e) { 808 | e.printStackTrace(); 809 | } 810 | } 811 | 812 | return null; 813 | } 814 | 815 | /** 816 | * Transforms Calendar to ISO 8601 string. 817 | **/ 818 | public static String fromCalendar(final Calendar calendar) { 819 | // TODO: move this method to DateUtils 820 | Date date = calendar.getTime(); 821 | String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(date); 822 | return formatted.substring(0, 22) + ":" + formatted.substring(22); 823 | } 824 | 825 | /** 826 | * Gets current date and time formatted as ISO 8601 string. 827 | **/ 828 | public static String now() { 829 | // TODO: move this method to DateUtils 830 | return fromCalendar(GregorianCalendar.getInstance()); 831 | } 832 | 833 | /** 834 | * Transforms ISO 8601 string to Calendar. 835 | **/ 836 | public static Calendar toCalendar(final String iso8601string) throws ParseException { 837 | // TODO: move this method to DateUtils 838 | Calendar calendar = GregorianCalendar.getInstance(); 839 | String s = iso8601string.replace("Z", "+00:00"); 840 | try { 841 | s = s.substring(0, 22) + s.substring(23); 842 | } catch (IndexOutOfBoundsException e) { 843 | // throw new org.apache.http.ParseException(); 844 | e.printStackTrace(); 845 | } 846 | 847 | Date date = null; 848 | try { 849 | date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s); 850 | } catch (java.text.ParseException e) { 851 | e.printStackTrace(); 852 | } 853 | calendar.setTime(date); 854 | return calendar; 855 | } 856 | 857 | /** 858 | * @param time ISO formatted time when the event occurred in local time zone. 859 | * @deprecated Totally bloated code. 860 | * Calculates the elapsed time after the given parameter date. 861 | **/ 862 | public static String getElapsedTime(String time) { 863 | TimeZone defaultTimeZone = TimeZone.getDefault(); 864 | 865 | // TODO: its advisable not to use this method as it changes the 866 | // timezone. 867 | // Change it at some time in future. 868 | TimeZone.setDefault(TimeZone.getTimeZone("UTC")); 869 | 870 | Date eventTime = DateUtils.parseDate(time); 871 | 872 | Date currentDate = new Date(); 873 | 874 | long diffInSeconds = (currentDate.getTime() - eventTime.getTime()) / 1000; 875 | String elapsed = ""; 876 | long seconds = diffInSeconds; 877 | long mins = diffInSeconds / 60; 878 | long hours = diffInSeconds / (60 * 60); 879 | long days = diffInSeconds / 86400; 880 | long weeks = diffInSeconds / 604800; 881 | long months = diffInSeconds / 2592000; 882 | 883 | // Log.v( TAG, "#getElapsedTime seconds: " + seconds + " mins: " + mins 884 | // + " hours: " + hours + " days: " + days ); 885 | 886 | if (seconds < 120) { 887 | elapsed = "a min ago"; 888 | } else if (mins < 60) { 889 | elapsed = mins + " mins ago"; 890 | } else if (hours < 24) { 891 | elapsed = hours + " " + (hours > 1 ? "hrs" : "hr") + " ago"; 892 | } else if (hours < 48) { 893 | elapsed = "a day ago"; 894 | } else if (days < 7) { 895 | elapsed = days + " days ago"; 896 | } else if (weeks < 5) { 897 | elapsed = weeks + " " + (weeks > 1 ? "weeks" : "week") + " ago"; 898 | } else if (months < 12) { 899 | elapsed = months + " " + (months > 1 ? "months" : "months") + " ago"; 900 | } else { 901 | elapsed = "more than a year ago"; 902 | } 903 | 904 | TimeZone.setDefault(defaultTimeZone); 905 | 906 | return elapsed; 907 | } 908 | 909 | /** 910 | * Set Mock Location for test device. DDMS cannot be used to mock location on an actual device. 911 | * So this method should be used which forces the GPS Provider to mock the location on an actual 912 | * device. 913 | **/ 914 | public static void setMockLocation(Context ctx, double longitude, double latitude) { 915 | // use application level context to avoid unnecessary leaks. 916 | LocationManager locationManager = (LocationManager) ctx.getApplicationContext().getSystemService(Context.LOCATION_SERVICE); 917 | 918 | locationManager.addTestProvider(LocationManager.GPS_PROVIDER, "requiresNetwork" == "", "requiresSatellite" == "", "requiresCell" == "", "hasMonetaryCost" == "", "supportsAltitude" == "", "supportsSpeed" == "", "supportsBearing" == "", 919 | 920 | android.location.Criteria.POWER_LOW, android.location.Criteria.ACCURACY_FINE); 921 | 922 | Location newLocation = new Location(LocationManager.GPS_PROVIDER); 923 | 924 | newLocation.setLongitude(longitude); 925 | newLocation.setLatitude(latitude); 926 | newLocation.setTime(new Date().getTime()); 927 | 928 | newLocation.setAccuracy(500); 929 | 930 | locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true); 931 | 932 | locationManager.setTestProviderStatus(LocationManager.GPS_PROVIDER, LocationProvider.AVAILABLE, null, System.currentTimeMillis()); 933 | 934 | // http://jgrasstechtips.blogspot.it/2012/12/android-incomplete-location-object.html 935 | makeLocationObjectComplete(newLocation); 936 | 937 | locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, newLocation); 938 | } 939 | 940 | private static void makeLocationObjectComplete(Location newLocation) { 941 | Method locationJellyBeanFixMethod = null; 942 | try { 943 | locationJellyBeanFixMethod = Location.class.getMethod("makeComplete"); 944 | } catch (NoSuchMethodException e) { 945 | e.printStackTrace(); 946 | } 947 | 948 | if (locationJellyBeanFixMethod != null) { 949 | try { 950 | locationJellyBeanFixMethod.invoke(newLocation); 951 | } catch (IllegalArgumentException e) { 952 | e.printStackTrace(); 953 | } catch (IllegalAccessException e) { 954 | e.printStackTrace(); 955 | } catch (InvocationTargetException e) { 956 | e.printStackTrace(); 957 | } 958 | } 959 | } 960 | 961 | /** 962 | * Gets the name of the day of the week. 963 | * 964 | * @param date ISO format date 965 | * @return The name of the day of the week 966 | **/ 967 | public static String getDayOfWeek(String date) { 968 | // TODO: move to DateUtils 969 | Date dateDT = DateUtils.parseDate(date); 970 | 971 | if (dateDT == null) { 972 | return null; 973 | } 974 | 975 | // Get current date 976 | Calendar c = Calendar.getInstance(); 977 | // it is very important to 978 | // set the date of 979 | // the calendar. 980 | c.setTime(dateDT); 981 | int day = c.get(Calendar.DAY_OF_WEEK); 982 | 983 | String dayStr = null; 984 | 985 | switch (day) { 986 | 987 | case Calendar.SUNDAY: 988 | dayStr = "Sunday"; 989 | break; 990 | 991 | case Calendar.MONDAY: 992 | dayStr = "Monday"; 993 | break; 994 | 995 | case Calendar.TUESDAY: 996 | dayStr = "Tuesday"; 997 | break; 998 | 999 | case Calendar.WEDNESDAY: 1000 | dayStr = "Wednesday"; 1001 | break; 1002 | 1003 | case Calendar.THURSDAY: 1004 | dayStr = "Thursday"; 1005 | break; 1006 | 1007 | case Calendar.FRIDAY: 1008 | dayStr = "Friday"; 1009 | break; 1010 | 1011 | case Calendar.SATURDAY: 1012 | dayStr = "Saturday"; 1013 | break; 1014 | } 1015 | 1016 | return dayStr; 1017 | } 1018 | 1019 | /** 1020 | * Gets random color integer 1021 | **/ 1022 | public static int getRandomColor() { 1023 | Random random = new Random(); 1024 | int red = random.nextInt(255); 1025 | int green = random.nextInt(255); 1026 | int blue = random.nextInt(255); 1027 | 1028 | return Color.argb(255, red, green, blue); 1029 | } 1030 | 1031 | /** 1032 | * Converts a given bitmap to byte array 1033 | */ 1034 | public static byte[] toBytes(Bitmap bmp) { 1035 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 1036 | bmp.compress(Bitmap.CompressFormat.PNG, 100, stream); 1037 | return stream.toByteArray(); 1038 | } 1039 | 1040 | /** 1041 | * Resizes an image to the given width and height parameters Prefer using 1042 | * 1043 | * @param sourceBitmap Bitmap to be resized 1044 | * @param newWidth Width of resized bitmap 1045 | * @param newHeight Height of the resized bitmap 1046 | */ 1047 | public static Bitmap resizeImage(Bitmap sourceBitmap, int newWidth, int newHeight, boolean filter) { 1048 | // TODO: move this method to ImageUtils 1049 | if (sourceBitmap == null) { 1050 | throw new NullPointerException("Bitmap to be resized cannot be null"); 1051 | } 1052 | 1053 | Bitmap resized = null; 1054 | 1055 | if (sourceBitmap.getWidth() < sourceBitmap.getHeight()) { 1056 | // image is portrait 1057 | resized = Bitmap.createScaledBitmap(sourceBitmap, newHeight, newWidth, true); 1058 | } else { 1059 | // image is landscape 1060 | resized = Bitmap.createScaledBitmap(sourceBitmap, newWidth, newHeight, true); 1061 | } 1062 | 1063 | resized = Bitmap.createScaledBitmap(sourceBitmap, newWidth, newHeight, true); 1064 | 1065 | return resized; 1066 | } 1067 | 1068 | /** 1069 | *
1070 | *
1071 | * 1072 | * @param compressionFactor Powers of 2 are often faster/easier for the decoder to honor 1073 | */ 1074 | public static Bitmap compressImage(Bitmap sourceBitmap, int compressionFactor) { 1075 | BitmapFactory.Options opts = new BitmapFactory.Options(); 1076 | opts.inPreferredConfig = Config.ARGB_8888; 1077 | opts.inSampleSize = compressionFactor; 1078 | 1079 | if (Build.VERSION.SDK_INT >= 10) { 1080 | opts.inPreferQualityOverSpeed = true; 1081 | } 1082 | 1083 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 1084 | sourceBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); 1085 | byte[] byteArray = stream.toByteArray(); 1086 | 1087 | Bitmap image = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, opts); 1088 | 1089 | return image; 1090 | } 1091 | 1092 | private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 1093 | // Raw height and width of image 1094 | final int height = options.outHeight; 1095 | final int width = options.outWidth; 1096 | int inSampleSize = 1; 1097 | 1098 | if (height > reqHeight || width > reqWidth) { 1099 | 1100 | // Calculate ratios of height and width to requested height and 1101 | // width 1102 | final int heightRatio = Math.round((float) height / (float) reqHeight); 1103 | final int widthRatio = Math.round((float) width / (float) reqWidth); 1104 | 1105 | // Choose the smallest ratio as inSampleSize value, this will 1106 | // guarantee 1107 | // a final image with both dimensions larger than or equal to the 1108 | // requested height and width. 1109 | inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 1110 | } 1111 | 1112 | return inSampleSize; 1113 | } 1114 | 1115 | /** 1116 | * Provide the height to which the sourceImage is to be resized. This method will calculate the 1117 | * resultant height. Use scaleDownBitmap from {@link Utils} wherever possible 1118 | */ 1119 | public Bitmap resizeImageByHeight(int height, Bitmap sourceImage) { 1120 | // TODO: move this method to ImageUtils 1121 | int widthO = 0; // original width 1122 | int heightO = 0; // original height 1123 | int widthNew = 0; 1124 | int heightNew = 0; 1125 | 1126 | widthO = sourceImage.getWidth(); 1127 | heightO = sourceImage.getHeight(); 1128 | heightNew = height; 1129 | 1130 | // Maintain the aspect ratio 1131 | // of the original banner image. 1132 | widthNew = (heightNew * widthO) / heightO; 1133 | 1134 | return Bitmap.createScaledBitmap(sourceImage, widthNew, heightNew, true); 1135 | } 1136 | 1137 | /** 1138 | * Checks if the url is valid 1139 | */ 1140 | public static boolean isValidURL(String url) { 1141 | URL urlObj; 1142 | 1143 | try { 1144 | urlObj = new URL(url); 1145 | } catch (MalformedURLException e) { 1146 | return false; 1147 | } 1148 | 1149 | try { 1150 | urlObj.toURI(); 1151 | } catch (URISyntaxException e) { 1152 | return false; 1153 | } 1154 | 1155 | return true; 1156 | } 1157 | 1158 | @Nullable 1159 | /** 1160 | * @return Lower case string for one of above listed media type 1161 | * @deprecated Use {@link MediaUtils#getMediaType(Uri)} 1162 | * Get the type of the media. Audio, Video or Image. 1163 | */ 1164 | public static String getMediaType(String contentType) { 1165 | if (isMedia(contentType)) { 1166 | if (isVideo(contentType)) { 1167 | return "video"; 1168 | } else if (isAudio(contentType)) { 1169 | return "audio"; 1170 | } else if (isImage(contentType)) { 1171 | return "image"; 1172 | } else { 1173 | return null; 1174 | } 1175 | } else { 1176 | return null; 1177 | } 1178 | } 1179 | 1180 | /** 1181 | * @param mimeType standard MIME type of the data. 1182 | * @deprecated {@link MediaUtils#isMedia(String)} 1183 | * Identifies if the content represented by the parameter mimeType is media. Image, Audio and 1184 | * Video is treated as media by this method. You can refer to standard MIME type here. Standard MIME 1186 | * types. 1187 | */ 1188 | public static boolean isMedia(String mimeType) { 1189 | boolean isMedia = false; 1190 | 1191 | if (mimeType != null) { 1192 | if (mimeType.startsWith("image/") || mimeType.startsWith("video/") || mimeType.startsWith("audio/")) { 1193 | isMedia = true; 1194 | } 1195 | } else { 1196 | isMedia = false; 1197 | } 1198 | 1199 | return isMedia; 1200 | } 1201 | 1202 | /** 1203 | * Gets the Uri without the fragment. For e.g if the uri is 1204 | * content://com.android.storage/data/images/48829#is_png the part after '#' is called as 1205 | * fragment. This method strips the fragment and returns the url. 1206 | */ 1207 | public static String removeUriFragment(String url) { 1208 | 1209 | if (url == null || url.length() == 0) { 1210 | return null; 1211 | } 1212 | 1213 | String[] arr = url.split("#"); 1214 | 1215 | if (arr.length == 2) { 1216 | return arr[0]; 1217 | } else { 1218 | return url; 1219 | } 1220 | } 1221 | 1222 | /** 1223 | * Removes the parameters from the query from the uri 1224 | */ 1225 | public static String removeQueryParameters(Uri uri) { 1226 | assert (uri.getAuthority() != null); 1227 | assert (uri.getPath() != null); 1228 | Uri.Builder builder = new Uri.Builder(); 1229 | builder.scheme(uri.getScheme()); 1230 | builder.encodedAuthority(uri.getAuthority()); 1231 | builder.encodedPath(uri.getPath()); 1232 | return builder.build().toString(); 1233 | } 1234 | 1235 | /** 1236 | * @deprecated Use {@link MediaUtils#isImage(String)} 1237 | * Returns true if the mime type is a standard image mime type 1238 | */ 1239 | public static boolean isImage(String mimeType) { 1240 | if (mimeType != null) { 1241 | if (mimeType.startsWith("image/")) { 1242 | return true; 1243 | } else { 1244 | return false; 1245 | } 1246 | } else { 1247 | return false; 1248 | } 1249 | } 1250 | 1251 | /** 1252 | * @deprecated Use {@link MediaUtils#isAudio(String)} 1253 | * Returns true if the mime type is a standard audio mime type 1254 | */ 1255 | public static boolean isAudio(String mimeType) { 1256 | if (mimeType != null) { 1257 | if (mimeType.startsWith("audio/")) { 1258 | return true; 1259 | } else { 1260 | return false; 1261 | } 1262 | } else { 1263 | return false; 1264 | } 1265 | } 1266 | 1267 | /** 1268 | * @deprecated Use {@link MediaUtils#isVideo(String)} 1269 | * Returns true if the mime type is a standard video mime type 1270 | */ 1271 | public static boolean isVideo(String mimeType) { 1272 | if (mimeType != null) { 1273 | if (mimeType.startsWith("video/")) { 1274 | return true; 1275 | } else { 1276 | return false; 1277 | } 1278 | } else { 1279 | return false; 1280 | } 1281 | } 1282 | 1283 | @Nullable 1284 | /** 1285 | * @deprecated This is a monster that will lead to OutOfMemory exception some day and the world 1286 | * will come to an end. 1287 | * Gets the media data from the one of the following media {@link android.content.ContentProvider} This method 1288 | * should not be called from the main thread of the application. Calling this method may have 1289 | * performance issues as this may allocate a huge memory array. 1290 | *

    1291 | *
  • {@link android.provider.MediaStore.Images.Media}
  • 1292 | *
  • {@link android.provider.MediaStore.Audio.Media}
  • 1293 | *
  • {@link android.provider.MediaStore.Video.Media}
  • 1294 | *
1295 | * 1296 | * @param context Context object 1297 | * @param uri Media content uri of the image, audio or video resource 1298 | */ 1299 | public static byte[] getMediaData(Context context, Uri uri) { 1300 | if (uri == null) { 1301 | throw new NullPointerException("Uri cannot be null"); 1302 | } 1303 | 1304 | Cursor cursor = context.getContentResolver().query(uri, new String[]{Media.DATA}, null, null, null); 1305 | byte[] data = null; 1306 | 1307 | try { 1308 | if (cursor != null && cursor.getCount() > 0) { 1309 | if (cursor.moveToNext()) { 1310 | String path = cursor.getString(cursor.getColumnIndex(Media.DATA)); 1311 | 1312 | try { 1313 | File file = new File(path); 1314 | FileInputStream fileInputStream = new FileInputStream(file); 1315 | data = readStreamToBytes(fileInputStream); 1316 | } catch (FileNotFoundException e) { 1317 | e.printStackTrace(); 1318 | } catch (Exception e) { 1319 | e.printStackTrace(); 1320 | } 1321 | 1322 | // Log.v( TAG, "#getVideoData byte.size: " + data.length ); 1323 | } // end while 1324 | } else { 1325 | Log.e(TAG, "#getMediaData cur is null or blank"); 1326 | } 1327 | } finally { 1328 | if (cursor != null && !cursor.isClosed()) { 1329 | cursor.close(); 1330 | } 1331 | } 1332 | 1333 | return data; 1334 | } 1335 | 1336 | /** 1337 | * Convert {@linkplain java.io.InputStream} to byte array. 1338 | * 1339 | * @throws NullPointerException If input parameter {@link java.io.InputStream} is null 1340 | **/ 1341 | public static byte[] readStreamToBytes(InputStream inputStream) { 1342 | 1343 | if (inputStream == null) { 1344 | throw new NullPointerException("InputStream is null"); 1345 | } 1346 | 1347 | byte[] bytesData = null; 1348 | BufferedReader reader = null; 1349 | try { 1350 | reader = new BufferedReader(new InputStreamReader(inputStream)); 1351 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 1352 | 1353 | int nRead; 1354 | byte[] data = new byte[16384]; 1355 | 1356 | while ((nRead = inputStream.read(data, 0, data.length)) != -1) { 1357 | buffer.write(data, 0, nRead); 1358 | } 1359 | 1360 | buffer.flush(); 1361 | 1362 | bytesData = buffer.toByteArray(); 1363 | 1364 | // Log.d( TAG, "#readStream data: " + data ); 1365 | } catch (IOException e) { 1366 | e.printStackTrace(); 1367 | } catch (Exception e) { 1368 | e.printStackTrace(); 1369 | } finally { 1370 | 1371 | if (reader != null) { 1372 | try { 1373 | reader.close(); 1374 | 1375 | if (inputStream != null) 1376 | inputStream.close(); 1377 | } catch (IOException e) { 1378 | e.printStackTrace(); 1379 | } catch (Exception e) { 1380 | e.printStackTrace(); 1381 | } 1382 | } 1383 | } // finally 1384 | 1385 | return bytesData; 1386 | } 1387 | 1388 | /** 1389 | * @param mediaUri uri to the media resource. For e.g. content://media/external/images/media/45490 or 1390 | * content://media/external/video/media/45490 1391 | * @return Size in bytes 1392 | * @deprecated Use {@link MediaUtils#getMediaSize(Context, Uri)} 1393 | * Gets the size of the media resource pointed to by the paramter mediaUri. 1394 | *

1395 | * Known bug: for unknown reason, the image size for some images was found to be 0 1396 | **/ 1397 | public static long getMediaSize(Context context, Uri mediaUri) { 1398 | Cursor cur = context.getContentResolver().query(mediaUri, new String[]{Media.SIZE}, null, null, null); 1399 | long size = -1; 1400 | 1401 | try { 1402 | if (cur != null && cur.getCount() > 0) { 1403 | while (cur.moveToNext()) { 1404 | size = cur.getLong(cur.getColumnIndex(Media.SIZE)); 1405 | 1406 | // for unknown reason, the image size for image was found to 1407 | // be 0 1408 | // Log.v( TAG, "#getSize byte.size: " + size ); 1409 | 1410 | if (size == 0) 1411 | Log.w(TAG, "#getSize The media size was found to be 0. Reason: UNKNOWN"); 1412 | 1413 | } // end while 1414 | } else if (cur.getCount() == 0) { 1415 | Log.e(TAG, "#getMediaSize cur size is 0. File may not exist"); 1416 | } else { 1417 | Log.e(TAG, "#getMediaSize cur is null"); 1418 | } 1419 | } finally { 1420 | if (cur != null && !cur.isClosed()) { 1421 | cur.close(); 1422 | } 1423 | } 1424 | 1425 | return size; 1426 | } 1427 | 1428 | /** 1429 | * @deprecated {@link MediaUtils#getMediaFileName(Context, Uri)} 1430 | * Gets media file name. 1431 | **/ 1432 | public static String getMediaFileName(Context ctx, Uri mediaUri) { 1433 | String colName = MediaColumns.DISPLAY_NAME; 1434 | Cursor cur = ctx.getContentResolver().query(mediaUri, new String[]{colName}, null, null, null); 1435 | String dispName = null; 1436 | 1437 | try { 1438 | if (cur != null && cur.getCount() > 0) { 1439 | while (cur.moveToNext()) { 1440 | dispName = cur.getString(cur.getColumnIndex(colName)); 1441 | 1442 | // for unknown reason, the image size for image was found to 1443 | // be 0 1444 | // Log.v( TAG, "#getMediaFileName byte.size: " + size ); 1445 | 1446 | if (TextUtils.isEmpty(colName)) { 1447 | Log.w(TAG, "#getMediaFileName The file name is blank or null. Reason: UNKNOWN"); 1448 | } 1449 | 1450 | } // end while 1451 | } else if (cur != null && cur.getCount() == 0) { 1452 | Log.e(TAG, "#getMediaFileName File may not exist"); 1453 | } else { 1454 | Log.e(TAG, "#getMediaFileName cur is null"); 1455 | } 1456 | } finally { 1457 | if (cur != null && !cur.isClosed()) { 1458 | cur.close(); 1459 | } 1460 | } 1461 | 1462 | return dispName; 1463 | } 1464 | 1465 | @Nullable 1466 | /** 1467 | * @deprecated Use {@link MediaUtils#getMediaType(Uri)} 1468 | * Gets media type from the Uri. 1469 | */ 1470 | public static String getMediaType(Uri uri) { 1471 | if (uri == null) { 1472 | return null; 1473 | } 1474 | 1475 | String uriStr = uri.toString(); 1476 | 1477 | if (uriStr.contains("video")) { 1478 | return "video"; 1479 | } else if (uriStr.contains("audio")) { 1480 | return "audio"; 1481 | } else if (uriStr.contains("image")) { 1482 | return "image"; 1483 | } else { 1484 | return null; 1485 | } 1486 | } 1487 | 1488 | /** 1489 | * @param sourceText String to be converted to bold. 1490 | * @deprecated Use {@link #toBold(String, String)} 1491 | * Returns {@link android.text.SpannableString} in Bold typeface 1492 | */ 1493 | public static SpannableStringBuilder toBold(String sourceText) { 1494 | 1495 | if (sourceText == null) { 1496 | throw new NullPointerException("String to convert cannot be bold"); 1497 | } 1498 | 1499 | final SpannableStringBuilder sb = new SpannableStringBuilder(sourceText); 1500 | 1501 | // Span to set text color to some RGB value 1502 | final StyleSpan bss = new StyleSpan(android.graphics.Typeface.BOLD); 1503 | 1504 | // set text bold 1505 | sb.setSpan(bss, 0, sb.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); 1506 | return sb; 1507 | } 1508 | 1509 | /** 1510 | * Typefaces the string as bold. 1511 | * If sub-string is null, entire string will be typefaced as bold and returned. 1512 | * 1513 | * @param string 1514 | * @param subString The subString within the string to bold. Pass null to bold entire string. 1515 | * @return {@link android.text.SpannableString} 1516 | */ 1517 | public static SpannableStringBuilder toBold(String string, String subString) { 1518 | if (TextUtils.isEmpty(string)) { 1519 | return new SpannableStringBuilder(""); 1520 | } 1521 | 1522 | SpannableStringBuilder spannableBuilder = new SpannableStringBuilder(string); 1523 | 1524 | StyleSpan bss = new StyleSpan(Typeface.BOLD); 1525 | if (subString != null) { 1526 | int substringNameStart = string.toLowerCase().indexOf(subString); 1527 | if (substringNameStart > -1) { 1528 | spannableBuilder.setSpan(bss, substringNameStart, substringNameStart + subString.length(), 1529 | Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 1530 | } 1531 | } else { 1532 | // set entire text to bold 1533 | spannableBuilder.setSpan(bss, 0, spannableBuilder.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); 1534 | } 1535 | return spannableBuilder; 1536 | } 1537 | 1538 | /** 1539 | * Formats given size in bytes to KB, MB, GB or whatever. This will work up to 1000 TB 1540 | */ 1541 | public static String formatSize(long size) { 1542 | 1543 | if (size <= 0) return "0"; 1544 | 1545 | final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"}; 1546 | int digitGroups = (int) (Math.log10(size) / Math.log10(1024)); 1547 | return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; 1548 | } 1549 | 1550 | /** 1551 | * Formats given size in bytes to KB, MB, GB or whatever. Preferably use this method for 1552 | * performance efficiency. 1553 | * 1554 | * @param si Controls byte value precision. If true, formatting is done using approx. 1000 Uses 1555 | * 1024 if false. 1556 | **/ 1557 | public static String formatSize(long bytes, boolean si) { 1558 | int unit = si ? 1000 : 1024; 1559 | 1560 | if (bytes < unit) { 1561 | return bytes + " B"; 1562 | } 1563 | 1564 | int exp = (int) (Math.log(bytes) / Math.log(unit)); 1565 | String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); 1566 | return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); 1567 | } 1568 | 1569 | /** 1570 | * Creates the uri to a file located on external storage or application internal storage. 1571 | */ 1572 | public static Uri createUri(Context ctx) { 1573 | File root = getStorageDirectory(ctx, null); 1574 | root.mkdirs(); 1575 | File file = new File(root, Long.toString(new Date().getTime())); 1576 | Uri uri = Uri.fromFile(file); 1577 | 1578 | return uri; 1579 | } 1580 | 1581 | /** 1582 | * @param ctx 1583 | * @param savingUri 1584 | * @param durationInSeconds 1585 | * @return 1586 | * @deprecated Use {@link MediaUtils#createTakeVideoIntent(Activity, Uri, int)} 1587 | * Creates an intent to take a video from camera or gallery or any other application that can 1588 | * handle the intent. 1589 | */ 1590 | public static Intent createTakeVideoIntent(Activity ctx, Uri savingUri, int durationInSeconds) { 1591 | 1592 | if (savingUri == null) { 1593 | throw new NullPointerException("Uri cannot be null"); 1594 | } 1595 | 1596 | final List cameraIntents = new ArrayList(); 1597 | final Intent captureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); 1598 | final PackageManager packageManager = ctx.getPackageManager(); 1599 | final List listCam = packageManager.queryIntentActivities(captureIntent, 0); 1600 | for (ResolveInfo res : listCam) { 1601 | final String packageName = res.activityInfo.packageName; 1602 | final Intent intent = new Intent(captureIntent); 1603 | intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); 1604 | intent.setPackage(packageName); 1605 | intent.putExtra(MediaStore.EXTRA_OUTPUT, savingUri); 1606 | intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationInSeconds); 1607 | cameraIntents.add(intent); 1608 | } 1609 | 1610 | // Filesystem. 1611 | final Intent galleryIntent = new Intent(); 1612 | galleryIntent.setType("video/*"); 1613 | galleryIntent.setAction(Intent.ACTION_GET_CONTENT); 1614 | 1615 | // Chooser of filesystem options. 1616 | final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source"); 1617 | 1618 | // Add the camera options. 1619 | chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{})); 1620 | 1621 | return chooserIntent; 1622 | } 1623 | 1624 | /** 1625 | * @param savingUri Uri to store a high resolution image at. If the user takes the picture using the 1626 | * camera the image will be stored at this uri. 1627 | * @deprecated Use {@link MediaUtils#createTakePictureIntent(Activity, Uri)} 1628 | * Creates a ACTION_IMAGE_CAPTURE photo & ACTION_GET_CONTENT intent. This intent will be 1629 | * aggregation of intents required to take picture from Gallery and Camera at the minimum. The 1630 | * intent will also be directed towards the apps that are capable of sourcing the image data. 1631 | * For e.g. Dropbox, Astro file manager. 1632 | **/ 1633 | public static Intent createTakePictureIntent(Activity ctx, Uri savingUri) { 1634 | 1635 | if (savingUri == null) { 1636 | throw new NullPointerException("Uri cannot be null"); 1637 | } 1638 | 1639 | final List cameraIntents = new ArrayList(); 1640 | final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 1641 | final PackageManager packageManager = ctx.getPackageManager(); 1642 | final List listCam = packageManager.queryIntentActivities(captureIntent, 0); 1643 | for (ResolveInfo res : listCam) { 1644 | final String packageName = res.activityInfo.packageName; 1645 | final Intent intent = new Intent(captureIntent); 1646 | intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); 1647 | intent.setPackage(packageName); 1648 | intent.putExtra(MediaStore.EXTRA_OUTPUT, savingUri); 1649 | cameraIntents.add(intent); 1650 | } 1651 | 1652 | // Filesystem. 1653 | final Intent galleryIntent = new Intent(); 1654 | galleryIntent.setType("image/*"); 1655 | galleryIntent.setAction(Intent.ACTION_GET_CONTENT); 1656 | 1657 | // Chooser of filesystem options. 1658 | final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source"); 1659 | 1660 | // Add the camera options. 1661 | chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{})); 1662 | 1663 | return chooserIntent; 1664 | } 1665 | 1666 | @Nullable 1667 | /** 1668 | * @deprecated Use {@link MediaUtils#createImageUri(Context)} 1669 | * Creates external content:// scheme uri to save the images at. The image saved at this 1670 | * {@link android.net.Uri} will be visible via the gallery application on the device. 1671 | */ 1672 | public static Uri createImageUri(Context ctx) throws IOException { 1673 | 1674 | if (ctx == null) { 1675 | throw new NullPointerException("Context cannot be null"); 1676 | } 1677 | 1678 | Uri imageUri = null; 1679 | 1680 | ContentValues values = new ContentValues(); 1681 | values.put(MediaColumns.TITLE, ""); 1682 | values.put(ImageColumns.DESCRIPTION, ""); 1683 | imageUri = ctx.getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values); 1684 | 1685 | return imageUri; 1686 | } 1687 | 1688 | @Nullable 1689 | /** 1690 | * @deprecated Use {@link MediaUtils#createVideoUri(Context)} 1691 | * Creates external content:// scheme uri to save the videos at. 1692 | */ 1693 | public static Uri createVideoUri(Context ctx) throws IOException { 1694 | 1695 | if (ctx == null) { 1696 | throw new NullPointerException("Context cannot be null"); 1697 | } 1698 | 1699 | Uri imageUri; 1700 | 1701 | ContentValues values = new ContentValues(); 1702 | values.put(MediaColumns.TITLE, ""); 1703 | values.put(ImageColumns.DESCRIPTION, ""); 1704 | imageUri = ctx.getContentResolver().insert(Video.Media.EXTERNAL_CONTENT_URI, values); 1705 | 1706 | return imageUri; 1707 | } 1708 | 1709 | @Nullable 1710 | /** 1711 | * 1712 | * @deprecated Use {#setTextValues} or {#getNullEmptyCheckedValue} 1713 | * Get the correctly appended name from the given name parameters 1714 | * 1715 | * @param firstName 1716 | * First name 1717 | * @param lastName 1718 | * Last name 1719 | * 1720 | * @return Returns correctly formatted full name. Returns null if both the values are null. 1721 | **/ 1722 | public static String getName(String firstName, String lastName) { 1723 | if (!TextUtils.isEmpty(firstName) && !TextUtils.isEmpty(lastName)) { 1724 | return firstName + " " + lastName; 1725 | } else if (!TextUtils.isEmpty(firstName)) { 1726 | return firstName; 1727 | } else if (!TextUtils.isEmpty(lastName)) { 1728 | return lastName; 1729 | } else { 1730 | return null; 1731 | } 1732 | } 1733 | 1734 | public static Bitmap roundBitmap(Bitmap bmp, int radius) { 1735 | Bitmap sbmp; 1736 | if (bmp.getWidth() != radius || bmp.getHeight() != radius) { 1737 | sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false); 1738 | } else { 1739 | sbmp = bmp; 1740 | } 1741 | 1742 | Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(), Config.ARGB_8888); 1743 | Canvas canvas = new Canvas(output); 1744 | 1745 | final Paint paint = new Paint(); 1746 | final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight()); 1747 | 1748 | paint.setAntiAlias(true); 1749 | paint.setFilterBitmap(true); 1750 | paint.setDither(true); 1751 | canvas.drawARGB(0, 0, 0, 0); 1752 | paint.setColor(Color.parseColor("#BAB399")); 1753 | canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f, sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint); 1754 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 1755 | canvas.drawBitmap(sbmp, rect, rect, paint); 1756 | 1757 | return output; 1758 | } 1759 | 1760 | /** 1761 | * Checks if given url is a relative path. 1762 | * 1763 | * @param url 1764 | * @return false if parameter url is null or false 1765 | */ 1766 | public static final boolean isRelativeUrl(String url) { 1767 | 1768 | if (TextUtils.isEmpty(url)) { 1769 | return false; 1770 | } 1771 | 1772 | Uri uri = Uri.parse(url); 1773 | 1774 | return uri.getScheme() == null; 1775 | } 1776 | 1777 | /** 1778 | * Checks if the parameter {@link android.net.Uri} is a content uri. 1779 | **/ 1780 | public static boolean isContentUri(Uri uri) { 1781 | if (!uri.toString().contains("content://")) { 1782 | return false; 1783 | } else { 1784 | return true; 1785 | } 1786 | } 1787 | 1788 | /** 1789 | * Hides the already popped up keyboard from the screen. 1790 | * 1791 | * @param context 1792 | */ 1793 | public static void hideKeyboard(Context context) { 1794 | try { 1795 | // use application level context to avoid unnecessary leaks. 1796 | InputMethodManager inputManager = (InputMethodManager) context.getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); 1797 | inputManager.hideSoftInputFromWindow(((Activity) context).getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); 1798 | } catch (Exception e) { 1799 | Log.e(TAG, "Sigh, cant even hide keyboard " + e.getMessage()); 1800 | } 1801 | } 1802 | 1803 | /** 1804 | * Checks if the build version passed as the parameter is 1805 | * lower than the current build version. 1806 | * 1807 | * @param buildVersion One of the values from {@link android.os.Build.VERSION_CODES} 1808 | * @return 1809 | */ 1810 | public static boolean isBuildBelow(int buildVersion) { 1811 | if (Build.VERSION.SDK_INT < buildVersion) return true; 1812 | else return false; 1813 | } 1814 | 1815 | /** 1816 | * Sets the two parameter values to the parameter {@link android.widget.TextView} 1817 | * in null-safe and empty-safe way. Such method can be used when setting firstname-lastname 1818 | * to a textview in the UI. 1819 | * 1820 | * @param textView 1821 | * @param firstValue String "null" will be treated as null value. 1822 | * @param secondValue String "null" will be treated as null value. 1823 | */ 1824 | public static void setTextValues(@NonNull TextView textView, @Nullable String firstValue, @Nullable String secondValue) { 1825 | String nullEmptyCheckedVal = getNullEmptyCheckedValue(firstValue, secondValue, null); 1826 | textView.setText(nullEmptyCheckedVal); 1827 | } 1828 | 1829 | @Nullable 1830 | /** 1831 | * Returns concatenated values of atleast to or more strings provided to it 1832 | * in a null safe manner. 1833 | * @param firstValue 1834 | * @param secondValue 1835 | * @param delimiter Delimiter to be used to concatnate the parameter strings. If null, space characer will be used. 1836 | * @param moreValues Optional 1837 | * @return 1838 | */ 1839 | public static String getNullEmptyCheckedValue(@Nullable String firstValue, @Nullable String secondValue, 1840 | @Nullable String delimiter, String... moreValues) { 1841 | if (TextUtils.isEmpty(delimiter)) { 1842 | delimiter = " "; 1843 | } 1844 | 1845 | StringBuilder builder = new StringBuilder(); 1846 | if (!TextUtils.isEmpty(firstValue) && !firstValue.equalsIgnoreCase("null") 1847 | && secondValue != null && !secondValue.equalsIgnoreCase("null")) { 1848 | builder.append(firstValue); 1849 | builder.append(delimiter); 1850 | builder.append(secondValue); 1851 | } else if (!TextUtils.isEmpty(firstValue) && !firstValue.equalsIgnoreCase("null")) { 1852 | builder.append(firstValue); 1853 | } else if (!TextUtils.isEmpty(secondValue) && !secondValue.equalsIgnoreCase("null")) { 1854 | builder.append(secondValue); 1855 | } 1856 | 1857 | if (moreValues != null) { 1858 | for (String value : moreValues) { 1859 | if (!TextUtils.isEmpty(value) && !value.equalsIgnoreCase("null")) { 1860 | builder.append(delimiter); 1861 | builder.append(value); 1862 | } 1863 | } 1864 | } 1865 | 1866 | return builder.toString(); 1867 | } 1868 | 1869 | @Nullable 1870 | /** 1871 | * Partially capitalizes the string from paramter start and offset. 1872 | * 1873 | * @param string String to be formatted 1874 | * @param start Starting position of the substring to be capitalized 1875 | * @param offset Offset of characters to be capitalized 1876 | * @return 1877 | */ 1878 | public static String capitalizeString(String string, int start, int offset) { 1879 | if (TextUtils.isEmpty(string)) { 1880 | return null; 1881 | } 1882 | String formattedString = string.substring(start, offset).toUpperCase() + string.substring(offset, string.length()); 1883 | return formattedString; 1884 | } 1885 | 1886 | @Nullable 1887 | /** 1888 | * Generates SHA-512 hash for given binary data. 1889 | * @param stringToHash 1890 | * @return 1891 | */ 1892 | public static String getSha512Hash(String stringToHash) { 1893 | if (stringToHash == null) { 1894 | return null; 1895 | } else { 1896 | return getSha512Hash(stringToHash.getBytes()); 1897 | } 1898 | } 1899 | 1900 | @Nullable 1901 | /** 1902 | * Generates SHA-512 hash for given binary data. 1903 | */ 1904 | public static String getSha512Hash(byte[] dataToHash) { 1905 | MessageDigest md = null; 1906 | try { 1907 | md = MessageDigest.getInstance("SHA-512"); 1908 | } catch (NoSuchAlgorithmException e) { 1909 | e.printStackTrace(); 1910 | } 1911 | 1912 | if (md != null) { 1913 | md.update(dataToHash); 1914 | byte byteData[] = md.digest(); 1915 | String base64 = Base64.encodeToString(byteData, Base64.DEFAULT); 1916 | 1917 | return base64; 1918 | } 1919 | return null; 1920 | } 1921 | 1922 | @Nullable 1923 | /** 1924 | * Gets the extension of a file. 1925 | */ 1926 | public static String getExtension(File file) { 1927 | String ext = null; 1928 | String s = file.getName(); 1929 | int i = s.lastIndexOf('.'); 1930 | 1931 | if (i > 0 && i < s.length() - 1) { 1932 | ext = s.substring(i + 1).toLowerCase(); 1933 | } 1934 | 1935 | return ext; 1936 | } 1937 | 1938 | } --------------------------------------------------------------------------------