├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ ├── README.md │ ├── assets │ │ └── features │ │ │ └── Settings.feature │ └── java │ │ └── de │ │ └── apkgrabber │ │ └── test │ │ ├── CucumberInstrumentation.java │ │ └── steps │ │ └── SettingsSteps.kt │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── de │ │ └── apkgrabber │ │ ├── activity │ │ └── MainActivity.java │ │ ├── adapter │ │ ├── ButtonBarAdapter.kt │ │ ├── InstalledAppAdapter.java │ │ ├── LogAdapter.java │ │ ├── MainActivityPageAdapter.java │ │ ├── SearchAdapter.java │ │ ├── UpdaterAdapter.kt │ │ └── UpdaterViewHolder.kt │ │ ├── dialog │ │ └── OwnPlayAccountDialog.kt │ │ ├── event │ │ ├── InstallAppEvent.java │ │ ├── InstalledAppTitleChange.java │ │ ├── PackageInstallerEvent.java │ │ ├── RefreshUpdateTitle.kt │ │ ├── SearchTitleChange.java │ │ ├── SnackBarEvent.java │ │ ├── UpdateFinalProgressEvent.java │ │ ├── UpdateInstalledAppsEvent.java │ │ ├── UpdateProgressEvent.java │ │ ├── UpdateStartEvent.java │ │ ├── UpdateStopEvent.java │ │ └── UpdaterTitleChange.java │ │ ├── fragment │ │ ├── AboutFragment.java │ │ ├── InstalledAppFragment.java │ │ ├── LogFragment.java │ │ ├── MainFragment.java │ │ ├── SearchFragment.java │ │ ├── SettingsFragment.java │ │ └── UpdaterFragment.java │ │ ├── model │ │ ├── APKMirror │ │ │ ├── AppExistsRequest.java │ │ │ ├── AppExistsResponse.java │ │ │ ├── AppExistsResponseApk.java │ │ │ ├── AppExistsResponseApp.java │ │ │ ├── AppExistsResponseData.java │ │ │ ├── AppExistsResponseDeveloper.java │ │ │ ├── AppExistsResponseHeaders.java │ │ │ └── AppExistsResponseRelease.java │ │ ├── ActionButton.kt │ │ ├── AppState.java │ │ ├── Constants.java │ │ ├── DownloadInfo.java │ │ ├── GitHub │ │ │ ├── Asset.java │ │ │ ├── Author.java │ │ │ ├── Release.java │ │ │ └── Uploader.java │ │ ├── IgnoreVersion.kt │ │ ├── InstallStatus.java │ │ ├── InstalledApp.java │ │ ├── LogMessage.java │ │ ├── MergedUpdate.kt │ │ └── Update.java │ │ ├── receiver │ │ ├── AlarmReceiver.java │ │ ├── BootReceiver.java │ │ ├── DownloadReceiver.java │ │ ├── NotificationClickReceiver.java │ │ └── SelfUpdateNotificationReceiver.java │ │ ├── service │ │ ├── AutomaticInstallerService.java │ │ ├── SelfUpdateService.java │ │ └── UpdaterService.java │ │ ├── updater │ │ ├── IUpdater.java │ │ ├── UpdaterAPKMirrorAPI.java │ │ ├── UpdaterAPKPure.java │ │ ├── UpdaterAptoide.java │ │ ├── UpdaterBase.java │ │ ├── UpdaterCallback.java │ │ ├── UpdaterGooglePlay.java │ │ ├── UpdaterNotification.java │ │ ├── UpdaterOptions.java │ │ ├── UpdaterStatus.java │ │ └── UpdaterUptodown.java │ │ ├── util │ │ ├── AlarmUtil.java │ │ ├── AnimationUtil.java │ │ ├── CollectionUtil.kt │ │ ├── ColorUtil.java │ │ ├── DownloadUtil.java │ │ ├── FileUtil.java │ │ ├── GenericCallback.java │ │ ├── GooglePlayUtil.java │ │ ├── InjektUtil.kt │ │ ├── InstalledAppUtil.java │ │ ├── LogUtil.java │ │ ├── MyBus.java │ │ ├── NotificationHelper.java │ │ ├── PixelConversion.java │ │ ├── ServiceUtil.java │ │ ├── SnackBarUtil.java │ │ ├── ThemeUtil.java │ │ ├── VersionUtil.java │ │ └── yalp │ │ │ ├── EglExtensionRetriever.java │ │ │ ├── NativeDeviceInfoProvider.java │ │ │ └── OkHttpClientAdapter.java │ │ └── view │ │ ├── CustomCardView.java │ │ ├── CustomViewPager.java │ │ ├── LogView.java │ │ └── UpdaterView.java │ └── res │ ├── anim │ ├── slide_in_left.xml │ ├── slide_in_right.xml │ ├── slide_out_left.xml │ └── slide_out_right.xml │ ├── drawable │ ├── banner.png │ ├── ic_android.xml │ ├── ic_beta.xml │ ├── ic_error.xml │ ├── ic_info.xml │ ├── ic_log.xml │ ├── ic_settings.xml │ ├── ic_update.xml │ └── ic_warning.xml │ ├── layout │ ├── activity_main.xml │ ├── button_bar_item.xml │ ├── dialog_own_play.xml │ ├── fragment_about.xml │ ├── fragment_installed_apps.xml │ ├── fragment_log.xml │ ├── fragment_main.xml │ ├── fragment_search.xml │ ├── fragment_updater.xml │ ├── installed_app_item.xml │ ├── log_item.xml │ ├── preference_category.xml │ └── updater_item.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-af │ └── strings.xml │ ├── values-ar │ └── strings.xml │ ├── values-da │ └── strings.xml │ ├── values-de │ └── strings.xml │ ├── values-es │ └── strings.xml │ ├── values-fr │ └── strings.xml │ ├── values-it │ └── strings.xml │ ├── values-nl │ └── strings.xml │ ├── values-pl │ └── strings.xml │ ├── values-pt │ └── strings.xml │ ├── values-ru │ └── strings.xml │ ├── values-tr │ └── strings.xml │ ├── values-zh │ └── strings.xml │ ├── values │ ├── arrays.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ ├── styles.xml │ └── ustrings.xml │ └── xml │ ├── preferences.xml │ └── share_paths.xml ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | gradle.properties 19 | build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # Intellij 37 | *.iml 38 | .idea/workspace.xml 39 | .idea/ 40 | 41 | # Keystore files 42 | *.jks 43 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | android: 3 | components: 4 | - tools 5 | - platform-tools 6 | - build-tools-26.0.0 7 | - android-26 8 | - extra-android-m2repository 9 | - extra-google-m2repository 10 | - extra-android-support 11 | licenses: 12 | - 'android-sdk-preview-license-.+' 13 | - 'android-sdk-license-.+' 14 | - 'intel-android-extra-license.+' 15 | jdk: 16 | - oraclejdk8 17 | before_install: 18 | - chmod +x gradlew 19 | script: 20 | - ./gradlew build 21 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | *In compliance with the [GPL-3.0](https://opensource.org/licenses/GPL-3.0) license: I declare that this version of the program contains my modifications, which can be seen through the usual "git" mechanism.* 2 | 3 | 4 | 2019-08 5 | Contributor(s): 6 | Dennis Hemker 7 | >Update README.md 8 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 9 | 10 | 11 | 2019-03 12 | Contributor(s): 13 | Dennis Hemker 14 | >Merge pull request #1 from hemker/dev 15 | >Update README.md 16 | >updated README.md 17 | >Merge pull request #3 from hemker/devAdding new APKMirror features 18 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 19 | 20 | 21 | 2019-02 22 | Contributor(s): 23 | Dennis Hemker 24 | >Update README.md 25 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 26 | 27 | 28 | 2017-07 29 | Contributor(s): 30 | rumboalla 31 | >Merge remote-tracking branch 'origin/master' 32 | >Update README.md 33 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 34 | 35 | 36 | 2017-06 37 | Contributor(s): 38 | rumboalla 39 | Gabriel 40 | >Merge pull request #181 from rumboalla/masterUpdate italian translation for Apkupdater 1.5.2... 41 | >Updating readme. 42 | >Now targeting API 26. 43 | >Merge remote-tracking branch 'origin/master' 44 | >Merge pull request #179 from Mrgts411/patch-1Update README.md 45 | >Update README.md 46 | >Create README.md 47 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 48 | 49 | 50 | 2017-04 51 | Contributor(s): 52 | rumboalla 53 | >Merge remote-tracking branch 'origin/master' 54 | >Update README.md 55 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 56 | 57 | 58 | 2017-03 59 | Contributor(s): 60 | rumboalla 61 | >Merge remote-tracking branch 'origin/master' 62 | >Update README.md 63 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 64 | 65 | 66 | 2017-02 67 | Contributor(s): 68 | rumboalla 69 | >Merge remote-tracking branch 'origin/master' 70 | >Update README.mdFixed link. 71 | >Update README.md 72 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 73 | 74 | 75 | 2016-08 76 | Contributor(s): 77 | rumboalla 78 | >Added extra information about the downloads for google play apps. 79 | >Added screenshots to README.md 80 | >Merge remote-tracking branch 'origin/master'Conflicts: README.md app/src/main/AndroidManifest.xml app/src/main/java/com/apkupdater/activity/MainActivity.java app/src/main/java/com/apkupdater/fragment/UpdaterFragment.java app/src/main/java/com/apkupdater/service/UpdaterService.java app/src/main/java/com/apkupdater/updater/UpdaterNotification.java app/src/main/java/com/apkupdater/util/AlarmUtil.java 81 | >Update README.md 82 | >Added README.md 83 | >Improved multi theme support. 84 | - - - - - - - - - - - - - - - - - - - - - - - - - - - 85 | 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Update Announcement 2 | Due to the advance in the original repository and other alternatives like AuroraStore, this repository is archived. 3 | 4 | # APKGrabber 5 | APKGrabber is a fork of [APKUpdater](https://github.com/rumboalla/apkupdater). Big thanks and of course 6 | all credits go to [rumboalla](https://github.com/rumboalla). 7 | I try to develop new features and maintain the software to stay available on latest android devices, 8 | but don't expect weekly updates. 9 | 10 | # Roadmap 11 | * [ ] Implementing more sources. 12 | - [x] Aptoide 13 | * [ ] Updating the build system, as it's full of deprecation warnings. 14 | 15 | # License 16 | Copyright © 2017 Rumboalla. 17 | Readapted 2019 by hemker. 18 | 19 | Licensed under the [GNU General Public License v3](https://www.gnu.org/licenses/gpl-3.0.en.html). 20 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 28 7 | buildToolsVersion "28.0.3" 8 | 9 | defaultConfig { 10 | applicationId "de.apkgrabber" 11 | minSdkVersion 14 12 | targetSdkVersion 28 13 | versionCode 44 14 | versionName "1.7.0" 15 | testApplicationId "de.apkgrabber.test" 16 | testInstrumentationRunner "de.apkgrabber.test.CucumberInstrumentation" 17 | multiDexEnabled true 18 | } 19 | 20 | applicationVariants.all { 21 | variant -> variant.resValue "string", "app_version", variant.versionName 22 | } 23 | 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 28 | } 29 | } 30 | 31 | sourceSets { 32 | androidTest { 33 | assets.srcDirs = ['src/androidTest/assets'] 34 | } 35 | } 36 | 37 | lintOptions { 38 | abortOnError false 39 | } 40 | 41 | packagingOptions { 42 | // Allow the compilation process to choose the dependencies for us. 43 | pickFirst "**" 44 | } 45 | } 46 | 47 | dependencies { 48 | // Annotation dependencies 49 | annotationProcessor "org.androidannotations:androidannotations:$aa_version" 50 | annotationProcessor "org.androidannotations:otto:$aa_version" 51 | 52 | // Compile dependencies 53 | compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 54 | compile "org.androidannotations:androidannotations-api:$aa_version" 55 | compile "com.android.support:appcompat-v7:28.0.0" 56 | compile "com.android.support:design:28.0.0" 57 | compile "com.android.support:preference-v7:28.0.0" 58 | compile "com.android.support:cardview-v7:28.0.0" 59 | compile "org.jsoup:jsoup:1.10.2" 60 | compile "com.squareup:otto:1.3.8" 61 | compile "com.google.code.gson:gson:2.8.0" 62 | compile "com.squareup.okhttp3:okhttp:3.8.0" 63 | compile "com.github.yeriomin:play-store-api:0.18" 64 | compile "eu.chainfire:libsuperuser:1.0.0.201704021214" 65 | compile "uy.kohesive.injekt:injekt-core:1.16.1" 66 | compile "com.fasterxml.jackson.core:jackson-databind:2.9.9" 67 | 68 | // Test dependencies 69 | testCompile "junit:junit:4.12" 70 | androidTestCompile "com.android.support:support-annotations:28.0.0" 71 | androidTestCompile "com.android.support.test.espresso:espresso-core:2.2.2" 72 | androidTestCompile "info.cukes:cucumber-android:1.2.5" 73 | } 74 | -------------------------------------------------------------------------------- /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 /Users/ramon/Library/Android/sdk/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 | -------------------------------------------------------------------------------- /app/src/androidTest/README.md: -------------------------------------------------------------------------------- 1 | BDD With Cucumber, Espresso and Kotlin 2 | ==================== 3 | 4 | Adding dependencies to build.gradle 5 | --------------------- 6 | ```Gradle 7 | testCompile "junit:junit:4.12" 8 | androidTestCompile "com.android.support:support-annotations:25.4.0" 9 | androidTestCompile "com.android.support.test.espresso:espresso-core:2.2.2" 10 | androidTestCompile "info.cukes:cucumber-android:1.2.5" 11 | ``` 12 | 13 | Adding source sets to build.gradle 14 | --------------------- 15 | ```Gradle 16 | sourceSets { 17 | androidTest { 18 | assets.srcDirs = ['src/androidTest/assets'] 19 | } 20 | } 21 | ``` 22 | 23 | Configuring test runner in build.gradle 24 | --------------------- 25 | ```Gradle 26 | testApplicationId "de.apkgrabber.test" 27 | testInstrumentationRunner "de.apkgrabber.test.CucumberInstrumentation" 28 | ``` 29 | 30 | Adding features to src/androidTest/assets/features 31 | --------------------- 32 | ```Gherkin 33 | Feature: Settings Feature 34 | 35 | Scenario: Go to settings 36 | Given I start the app 37 | When I go to settings 38 | Then I see the settings 39 | ``` 40 | 41 | Implementing CucumberInstrumentation (Java) 42 | --------------------- 43 | This can also be implemented with Kotlin. 44 | ```Java 45 | public class CucumberInstrumentation extends MonitoringInstrumentation { 46 | private final CucumberInstrumentationCore mInstrumentationCore = new CucumberInstrumentationCore(this); 47 | 48 | @Override 49 | public void onCreate(Bundle arguments) { 50 | super.onCreate(arguments); 51 | mInstrumentationCore.create(arguments); 52 | start(); 53 | } 54 | 55 | @Override 56 | public void onStart() { 57 | super.onStart(); 58 | waitForIdleSync(); 59 | mInstrumentationCore.start(); 60 | } 61 | } 62 | ``` 63 | 64 | Adding steps for our features (Kotlin) 65 | --------------------- 66 | ```Kotlin 67 | @CucumberOptions(features = arrayOf("features/Settings.feature")) 68 | class SettingsSteps: TestCase() 69 | // Implement 70 | } 71 | ``` -------------------------------------------------------------------------------- /app/src/androidTest/assets/features/Settings.feature: -------------------------------------------------------------------------------- 1 | Feature: Settings Feature 2 | 3 | Scenario: Go to settings 4 | Given I start the app 5 | When I go to settings 6 | Then I see the settings 7 | -------------------------------------------------------------------------------- /app/src/androidTest/java/de/apkgrabber/test/CucumberInstrumentation.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.test; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.os.Bundle; 6 | import android.support.test.runner.MonitoringInstrumentation; 7 | 8 | import cucumber.api.android.CucumberInstrumentationCore; 9 | 10 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | 12 | public class CucumberInstrumentation 13 | extends MonitoringInstrumentation 14 | { 15 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | 17 | private final CucumberInstrumentationCore mInstrumentationCore = new CucumberInstrumentationCore(this); 18 | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | @Override 22 | public void onCreate( 23 | Bundle arguments 24 | ) { 25 | super.onCreate(arguments); 26 | mInstrumentationCore.create(arguments); 27 | start(); 28 | } 29 | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | 32 | @Override 33 | public void onStart( 34 | ) { 35 | super.onStart(); 36 | waitForIdleSync(); 37 | mInstrumentationCore.start(); 38 | } 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | 42 | } 43 | 44 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/androidTest/java/de/apkgrabber/test/steps/SettingsSteps.kt: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.test.steps 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import org.junit.Before 6 | import org.junit.Rule 7 | 8 | import android.support.test.rule.ActivityTestRule 9 | 10 | import cucumber.api.CucumberOptions 11 | import cucumber.api.java.en.Given 12 | import cucumber.api.java.en.Then 13 | import cucumber.api.java.en.When 14 | 15 | import android.support.test.espresso.Espresso.onView 16 | import android.support.test.espresso.action.ViewActions.click 17 | import android.support.test.espresso.assertion.ViewAssertions.matches 18 | import android.support.test.espresso.matcher.ViewMatchers.* 19 | import de.apkgrabber.R 20 | 21 | import de.apkgrabber.activity.MainActivity_ 22 | import junit.framework.TestCase 23 | 24 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | @CucumberOptions(features = arrayOf("features/Settings.feature")) 27 | class SettingsSteps 28 | : TestCase() 29 | { 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | 32 | @Rule 33 | var mActivityRule = ActivityTestRule(MainActivity_::class.java, false, true) 34 | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | 37 | @Before 38 | public override fun setUp( 39 | ) { 40 | 41 | } 42 | 43 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | 45 | @Given("I start the app") 46 | fun i_start_the_app( 47 | ) { 48 | mActivityRule.launchActivity(null) 49 | } 50 | 51 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | 53 | @When("I go to settings") 54 | fun i_go_to_settings( 55 | ) { 56 | onView(withId(R.id.action_settings)).perform(click()) 57 | } 58 | 59 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 60 | 61 | @Then("I see the settings") 62 | fun i_see_the_settings( 63 | ) { 64 | onView(withText("Settings")).check(matches(isDisplayed())) 65 | } 66 | 67 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 | } 69 | 70 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 26 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 84 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/adapter/ButtonBarAdapter.kt: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.adapter 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context 6 | import android.support.v7.widget.RecyclerView 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import de.apkgrabber.R 11 | import de.apkgrabber.model.ActionButton 12 | import kotlinx.android.synthetic.main.button_bar_item.view.* 13 | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | class ButtonBarAdapter 17 | : RecyclerView.Adapter 18 | { 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | private var mItems: MutableList = mutableListOf() 22 | private var mContext: Context 23 | 24 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | constructor( 27 | context : Context 28 | ) { 29 | mContext = context 30 | } 31 | 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | 34 | override fun onBindViewHolder( 35 | holder: ButtonBarViewHolder, 36 | position: Int 37 | ) { 38 | holder?.bind(mItems[position]) 39 | } 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | override fun onCreateViewHolder( 44 | parent: ViewGroup, 45 | viewType: Int 46 | ): ButtonBarViewHolder { 47 | val v : View = LayoutInflater.from(parent?.context).inflate(R.layout.button_bar_item, parent, false) 48 | return ButtonBarViewHolder(v) 49 | } 50 | 51 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | 53 | override fun getItemCount( 54 | ): Int { 55 | return mItems.count() 56 | } 57 | 58 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | 60 | class ButtonBarViewHolder(view: View) 61 | : RecyclerView.ViewHolder(view) 62 | { 63 | private val mView : View = view 64 | 65 | fun bind( 66 | data : ActionButton 67 | ) { 68 | mView.button.text = data.text 69 | mView.button.setOnClickListener { data.callback() } 70 | if (data.loading) { 71 | mView.progress_bar.visibility = View.VISIBLE 72 | mView.button.visibility = View.INVISIBLE 73 | } else { 74 | mView.progress_bar.visibility = View.INVISIBLE 75 | mView.button.visibility = View.VISIBLE 76 | } 77 | } 78 | } 79 | 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | 82 | fun addButton( 83 | button : ActionButton 84 | ) { 85 | mItems.add(button) 86 | } 87 | 88 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 89 | 90 | } 91 | 92 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/adapter/LogAdapter.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.adapter; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.app.Activity; 6 | import android.content.Context; 7 | import android.support.annotation.NonNull; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ArrayAdapter; 11 | 12 | import de.apkgrabber.model.LogMessage; 13 | import de.apkgrabber.util.MyBus; 14 | import de.apkgrabber.view.LogView; 15 | import de.apkgrabber.view.LogView_; 16 | 17 | import org.androidannotations.annotations.Bean; 18 | import org.androidannotations.annotations.EBean; 19 | import org.androidannotations.annotations.RootContext; 20 | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | @EBean 24 | public class LogAdapter 25 | extends ArrayAdapter 26 | { 27 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | @RootContext 30 | Activity context; 31 | 32 | @Bean 33 | MyBus mBus; 34 | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | 37 | LogAdapter( 38 | Context context 39 | ) { 40 | super(context, 0); 41 | } 42 | 43 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | 45 | @Override 46 | @NonNull 47 | public View getView( 48 | int position, 49 | View convertView, 50 | @NonNull ViewGroup parent 51 | ) { 52 | LogView log; 53 | 54 | if (convertView == null) { 55 | log = LogView_.build(context); 56 | } else { 57 | log = (LogView) convertView; 58 | } 59 | 60 | log.bind(getItem(position)); 61 | 62 | return log; 63 | } 64 | 65 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 66 | 67 | @Override 68 | public void notifyDataSetChanged( 69 | ) { 70 | super.notifyDataSetChanged(); 71 | } 72 | 73 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 74 | 75 | } 76 | 77 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 78 | 79 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/adapter/MainActivityPageAdapter.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.adapter; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.app.FragmentManager; 8 | import android.support.v4.app.FragmentPagerAdapter; 9 | 10 | import de.apkgrabber.fragment.InstalledAppFragment_; 11 | import de.apkgrabber.fragment.SearchFragment; 12 | import de.apkgrabber.fragment.SearchFragment_; 13 | import de.apkgrabber.fragment.UpdaterFragment_; 14 | import de.apkgrabber.R; 15 | 16 | import java.security.InvalidParameterException; 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | public class MainActivityPageAdapter 21 | extends FragmentPagerAdapter 22 | { 23 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | 25 | private InstalledAppFragment_ mInstalledAppFragment = new InstalledAppFragment_(); 26 | private UpdaterFragment_ mUpdaterFragment = new UpdaterFragment_(); 27 | private SearchFragment mSearchFragment = new SearchFragment_(); 28 | private Context mContext; 29 | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | 32 | public MainActivityPageAdapter( 33 | Context context, 34 | FragmentManager fm 35 | ) { 36 | super(fm); 37 | mContext = context; 38 | } 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | 42 | @Override 43 | public Fragment getItem( 44 | int position 45 | ) { 46 | if (position == 0) { 47 | return mInstalledAppFragment; 48 | } else if (position == 1){ 49 | return mUpdaterFragment; 50 | } else if (position == 2){ 51 | return mSearchFragment; 52 | } else { 53 | throw new InvalidParameterException("Invalid position."); 54 | } 55 | } 56 | 57 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 58 | 59 | @Override 60 | public int getCount( 61 | ) { 62 | return 3; 63 | } 64 | 65 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 66 | 67 | @Override 68 | public CharSequence getPageTitle( 69 | int position 70 | ) { 71 | if (position == 0) { 72 | return mContext.getString(R.string.tab_installed); 73 | } else if (position == 1){ 74 | return mContext.getString(R.string.tab_updates); 75 | } else if (position == 2){ 76 | return mContext.getString(R.string.tab_search); 77 | } else { 78 | return "Error"; 79 | } 80 | } 81 | 82 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 83 | } 84 | 85 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 86 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/InstallAppEvent.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class InstallAppEvent 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private boolean success; 10 | private long id; 11 | private String packageName; 12 | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | public InstallAppEvent( 16 | String packageName, 17 | long id, 18 | boolean success 19 | ) { 20 | this.packageName = packageName; 21 | this.id = id; 22 | this.success = success; 23 | } 24 | 25 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | 27 | public String getPackageName() { 28 | return packageName; 29 | } 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | public boolean isSuccess() { 34 | return success; 35 | } 36 | 37 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | public long getId() { 40 | return id; 41 | } 42 | 43 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | } 45 | 46 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/InstalledAppTitleChange.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class InstalledAppTitleChange 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private String mTitle; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public InstalledAppTitleChange( 14 | String s 15 | ) { 16 | mTitle = s; 17 | } 18 | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | public String getTitle( 22 | ) { 23 | return mTitle; 24 | } 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | } 29 | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/PackageInstallerEvent.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Intent; 6 | 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | public class PackageInstallerEvent 10 | { 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | private Intent intent; 14 | private long id; 15 | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | public PackageInstallerEvent( 19 | Intent intent, 20 | long id 21 | ) { 22 | this.intent = intent; 23 | this.id = id; 24 | } 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | public Intent getIntent() { 29 | return intent; 30 | } 31 | 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | 34 | public long getId() { 35 | return id; 36 | } 37 | 38 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 39 | } 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/RefreshUpdateTitle.kt: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | class RefreshUpdateTitle {} 6 | 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/SearchTitleChange.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class SearchTitleChange 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private String mTitle; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public SearchTitleChange( 14 | String s 15 | ) { 16 | mTitle = s; 17 | } 18 | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | public String getTitle( 22 | ) { 23 | return mTitle; 24 | } 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | } 29 | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/SnackBarEvent.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class SnackBarEvent 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private String message; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public SnackBarEvent( 14 | String message 15 | ) { 16 | this.message = message; 17 | } 18 | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | public String getMessage() { 22 | return message; 23 | } 24 | 25 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | } 27 | 28 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/UpdateFinalProgressEvent.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import de.apkgrabber.model.Update; 6 | 7 | import java.util.List; 8 | 9 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | public class UpdateFinalProgressEvent 12 | { 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | private List mUpdate; 16 | 17 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | public UpdateFinalProgressEvent( 20 | List u 21 | ) { 22 | mUpdate = u; 23 | } 24 | 25 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | 27 | public List getUpdates( 28 | ) { 29 | return mUpdate; 30 | } 31 | 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | } 34 | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/UpdateInstalledAppsEvent.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class UpdateInstalledAppsEvent {} 6 | 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/UpdateProgressEvent.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import de.apkgrabber.model.Update; 6 | 7 | public class UpdateProgressEvent 8 | { 9 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | private Update mUpdate; 12 | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | public UpdateProgressEvent( 16 | Update u 17 | ) { 18 | mUpdate = u; 19 | } 20 | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | public Update getUpdate( 24 | ) { 25 | return mUpdate; 26 | } 27 | 28 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | } 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/UpdateStartEvent.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class UpdateStartEvent 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private int mNumUpdates; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public UpdateStartEvent( 14 | int n 15 | ) { 16 | mNumUpdates = n; 17 | } 18 | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | public int getNumUpdates( 22 | ) { 23 | return mNumUpdates; 24 | } 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | } 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/UpdateStopEvent.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class UpdateStopEvent 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private String mMessage; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public UpdateStopEvent( 14 | String m 15 | ) { 16 | mMessage = m; 17 | } 18 | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | public String getMessage( 22 | ) { 23 | return mMessage; 24 | } 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | } 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/event/UpdaterTitleChange.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.event; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class UpdaterTitleChange 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private String mTitle; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public UpdaterTitleChange( 14 | String s 15 | ) { 16 | mTitle = s; 17 | } 18 | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | public String getTitle( 22 | ) { 23 | return mTitle; 24 | } 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | } 29 | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/fragment/AboutFragment.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.fragment; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.os.Build; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.view.ViewCompat; 8 | import android.text.Html; 9 | import android.text.Spanned; 10 | import android.text.method.LinkMovementMethod; 11 | import android.view.View; 12 | import android.webkit.WebView; 13 | import android.webkit.WebViewClient; 14 | import android.widget.FrameLayout; 15 | import android.widget.TextView; 16 | 17 | import de.apkgrabber.R; 18 | import de.apkgrabber.model.Constants; 19 | import de.apkgrabber.util.ColorUtil; 20 | import de.apkgrabber.util.DownloadUtil; 21 | 22 | import org.androidannotations.annotations.AfterViews; 23 | import org.androidannotations.annotations.EFragment; 24 | import org.androidannotations.annotations.ViewById; 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | @EFragment(R.layout.fragment_about) 29 | public class AboutFragment 30 | extends Fragment 31 | { 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | 34 | @ViewById(R.id.app_name_text) 35 | protected TextView mAppNameText; 36 | 37 | @ViewById(R.id.app_version_text) 38 | protected TextView mAppVersionText; 39 | 40 | @ViewById(R.id.text_container) 41 | protected FrameLayout mTextContainer; 42 | 43 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | 45 | private WebView getWebView( 46 | ) { 47 | final WebView webView = new WebView(getContext()); 48 | 49 | webView.loadData(getString(R.string.app_description_html), "text/html", "UTF-8"); 50 | webView.setBackgroundColor(0x00000000); 51 | webView.getSettings().setDefaultFontSize(14); 52 | 53 | // Change the webview font color 54 | final String color = ColorUtil.getHexStringFromInt( mAppVersionText.getTextColors().getDefaultColor()); 55 | webView.getSettings().setJavaScriptEnabled(true); 56 | webView.setWebViewClient(new WebViewClient() { 57 | public void onPageFinished(WebView view, String url) { 58 | try { 59 | webView.loadUrl( 60 | "javascript:document.body.style.setProperty(\"color\", \"" + color + "\");" 61 | ); 62 | } catch (Exception ignored) { 63 | } 64 | } 65 | }); 66 | 67 | return webView; 68 | } 69 | 70 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | 72 | private TextView getTextView( 73 | ) { 74 | TextView textView = new TextView(getContext()); 75 | Spanned fromHtml; 76 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 77 | fromHtml = Html.fromHtml(getString(R.string.app_description_html), 0); 78 | }else{ 79 | //noinspection deprecation 80 | fromHtml = Html.fromHtml(getString(R.string.app_description_html)); 81 | } 82 | textView.setText(fromHtml); 83 | textView.setMovementMethod (LinkMovementMethod.getInstance()); 84 | return textView; 85 | } 86 | 87 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 88 | 89 | @AfterViews 90 | protected void onInit( 91 | ) { 92 | mAppNameText.setTextColor(ColorUtil.getColorFromTheme(getActivity().getTheme(), R.attr.colorAccent)); 93 | mAppNameText.setOnClickListener(new View.OnClickListener() { 94 | @Override 95 | public void onClick(View view) { 96 | DownloadUtil.launchBrowser(getContext(), Constants.GitHubURL); 97 | } 98 | }); 99 | 100 | try { 101 | WebView v = getWebView(); 102 | ViewCompat.setNestedScrollingEnabled(v, true); 103 | mTextContainer.addView(v); 104 | } catch (Exception e) { 105 | try { 106 | TextView v = getTextView(); 107 | ViewCompat.setNestedScrollingEnabled(v, true); 108 | mTextContainer.addView(v); 109 | } catch (Exception ignored) { 110 | 111 | } 112 | } 113 | } 114 | 115 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 116 | } 117 | 118 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 119 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/fragment/InstalledAppFragment.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.fragment; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.widget.SwipeRefreshLayout; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.support.v7.widget.SimpleItemAnimator; 10 | 11 | import android.util.Log; 12 | import de.apkgrabber.R; 13 | import de.apkgrabber.adapter.InstalledAppAdapter; 14 | import de.apkgrabber.event.InstalledAppTitleChange; 15 | import de.apkgrabber.event.UpdateInstalledAppsEvent; 16 | import de.apkgrabber.model.InstalledApp; 17 | import de.apkgrabber.updater.UpdaterOptions; 18 | import de.apkgrabber.util.GenericCallback; 19 | import de.apkgrabber.util.InstalledAppUtil; 20 | import de.apkgrabber.util.MyBus; 21 | import com.squareup.otto.Subscribe; 22 | 23 | import org.androidannotations.annotations.AfterViews; 24 | import org.androidannotations.annotations.Bean; 25 | import org.androidannotations.annotations.EFragment; 26 | import org.androidannotations.annotations.UiThread; 27 | import org.androidannotations.annotations.ViewById; 28 | 29 | import java.util.List; 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | @EFragment(R.layout.fragment_installed_apps) 34 | public class InstalledAppFragment 35 | extends Fragment 36 | { 37 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | @ViewById(R.id.list_view) 40 | RecyclerView mRecyclerView; 41 | 42 | @ViewById(R.id.swipe_container) 43 | SwipeRefreshLayout swipeRefreshLayout; 44 | 45 | @Bean 46 | InstalledAppUtil mInstalledAppUtil; 47 | 48 | @Bean 49 | MyBus mBus; 50 | 51 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | 53 | @AfterViews 54 | void init( 55 | ) { 56 | mBus.register(this); 57 | updateInstalledApps(new UpdateInstalledAppsEvent()); 58 | 59 | swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 60 | @Override 61 | public void onRefresh() { 62 | updateInstalledApps(new UpdateInstalledAppsEvent()); 63 | Log.d("InstalledAppFragmnet","refreshing..."); 64 | } 65 | }); 66 | } 67 | 68 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 69 | 70 | @Override 71 | public void onDestroy() { 72 | mBus.unregister(this); 73 | super.onDestroy(); 74 | } 75 | 76 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 77 | 78 | @Subscribe 79 | public void updateInstalledApps( 80 | UpdateInstalledAppsEvent ev 81 | ) { 82 | mInstalledAppUtil.getInstalledAppsAsync(getContext(), new GenericCallback>() { 83 | @Override 84 | public void onResult(List items) { 85 | setListAdapter(items); 86 | swipeRefreshLayout.setRefreshing(false); 87 | } 88 | }); 89 | } 90 | 91 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 92 | 93 | @UiThread(propagation = UiThread.Propagation.REUSE) 94 | protected void setListAdapter( 95 | List items 96 | ) { 97 | if (mRecyclerView == null || mBus == null) { 98 | return; 99 | } 100 | 101 | mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 102 | if (new UpdaterOptions(getContext()).disableAnimations()) { 103 | mRecyclerView.setItemAnimator(null); 104 | } else { 105 | ((SimpleItemAnimator) mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false); 106 | } 107 | mRecyclerView.setAdapter(new InstalledAppAdapter(getContext(), mRecyclerView, items)); 108 | mBus.post(new InstalledAppTitleChange(getString(R.string.tab_installed) + " (" + items.size() + ")")); 109 | } 110 | 111 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 112 | } 113 | 114 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 115 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/fragment/LogFragment.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.fragment; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.support.v4.app.Fragment; 6 | import android.widget.ListView; 7 | 8 | import de.apkgrabber.R; 9 | import de.apkgrabber.adapter.LogAdapter; 10 | import de.apkgrabber.model.LogMessage; 11 | import de.apkgrabber.util.AnimationUtil; 12 | import de.apkgrabber.util.MyBus; 13 | import com.squareup.otto.Subscribe; 14 | 15 | import org.androidannotations.annotations.AfterViews; 16 | import org.androidannotations.annotations.Bean; 17 | import org.androidannotations.annotations.EFragment; 18 | import org.androidannotations.annotations.ViewById; 19 | 20 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | @EFragment(R.layout.fragment_log) 23 | public class LogFragment 24 | extends Fragment 25 | { 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | @ViewById(R.id.list_view) 29 | ListView mListView; 30 | 31 | @Bean 32 | LogAdapter mAdapter; 33 | 34 | @Bean 35 | MyBus mBus; 36 | 37 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | @AfterViews 40 | public void init( 41 | ) { 42 | mListView.setAdapter(mAdapter); 43 | mBus.register(this); 44 | } 45 | 46 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 47 | 48 | @Override 49 | public void onDestroy( 50 | ) { 51 | super.onDestroy(); 52 | mBus.unregister(this); 53 | } 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | 57 | @Subscribe 58 | public void onMessage( 59 | LogMessage message 60 | ) { 61 | AnimationUtil.startSlideAnimation(getContext(), mListView); 62 | mAdapter.add(message); 63 | mAdapter.notifyDataSetChanged(); 64 | } 65 | 66 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 67 | 68 | } 69 | 70 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/fragment/MainFragment.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.fragment; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.design.widget.TabLayout; 8 | import android.support.v4.app.Fragment; 9 | 10 | import de.apkgrabber.R; 11 | import de.apkgrabber.adapter.MainActivityPageAdapter; 12 | import de.apkgrabber.event.InstalledAppTitleChange; 13 | import de.apkgrabber.event.SearchTitleChange; 14 | import de.apkgrabber.event.UpdaterTitleChange; 15 | import de.apkgrabber.model.AppState; 16 | import de.apkgrabber.util.MyBus; 17 | import de.apkgrabber.view.CustomViewPager; 18 | import com.squareup.otto.Subscribe; 19 | 20 | import org.androidannotations.annotations.AfterViews; 21 | import org.androidannotations.annotations.Bean; 22 | import org.androidannotations.annotations.EFragment; 23 | import org.androidannotations.annotations.UiThread; 24 | import org.androidannotations.annotations.ViewById; 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | @EFragment(R.layout.fragment_main) 29 | public class MainFragment 30 | extends Fragment 31 | { 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | 34 | @ViewById(R.id.container) 35 | CustomViewPager mViewPager; 36 | 37 | @ViewById(R.id.tabs) 38 | TabLayout mTabLayout; 39 | 40 | @Bean 41 | AppState mAppState; 42 | 43 | @Bean 44 | MyBus mBus; 45 | 46 | Bundle mSavedInstance; 47 | 48 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 49 | 50 | @Override 51 | public void onCreate( 52 | @Nullable Bundle savedInstanceState 53 | ) { 54 | mSavedInstance = savedInstanceState; 55 | super.onCreate(savedInstanceState); 56 | mBus.register(this); 57 | } 58 | 59 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 60 | 61 | @Override 62 | public void onDestroy() { 63 | mBus.unregister(this); 64 | super.onDestroy(); 65 | } 66 | 67 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 | 69 | @AfterViews 70 | void init( 71 | ) { 72 | mViewPager.setAdapter(new MainActivityPageAdapter(getContext(), getChildFragmentManager())); 73 | mViewPager.setOffscreenPageLimit(2); 74 | mTabLayout.setupWithViewPager(mViewPager); 75 | mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { 76 | @Override public void onTabSelected(TabLayout.Tab tab) { 77 | mAppState.setSelectedTab(tab.getPosition()); 78 | } 79 | @Override public void onTabUnselected(TabLayout.Tab tab) {} 80 | @Override public void onTabReselected(TabLayout.Tab tab) {} 81 | }); 82 | selectTab(mAppState.getSelectedTab()); 83 | } 84 | 85 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 86 | 87 | @Override 88 | public void onSaveInstanceState( 89 | Bundle outState 90 | ) { 91 | super.onSaveInstanceState(outState); 92 | } 93 | 94 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 95 | 96 | @Override 97 | public void onResume( 98 | ) { 99 | super.onResume(); 100 | 101 | // Select tab 102 | selectTab(mAppState.getSelectedTab()); 103 | } 104 | 105 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 106 | 107 | @Subscribe 108 | public void onInstalledAppTitleChange( 109 | InstalledAppTitleChange t 110 | ) { 111 | if (mTabLayout != null) { 112 | TabLayout.Tab selectedTab = mTabLayout.getTabAt(0); 113 | if (selectedTab != null) { 114 | selectedTab.setText(t.getTitle()); 115 | } 116 | } 117 | } 118 | 119 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 120 | 121 | @Subscribe 122 | public void onUpdaterTitleChange( 123 | UpdaterTitleChange t 124 | ) { 125 | if (mTabLayout != null) { 126 | TabLayout.Tab selectedTab = mTabLayout.getTabAt(1); 127 | if (selectedTab != null) { 128 | selectedTab.setText(t.getTitle()); 129 | } 130 | } 131 | } 132 | 133 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 134 | 135 | @Subscribe 136 | public void onSearchTitleChange( 137 | SearchTitleChange t 138 | ) { 139 | if (mTabLayout != null) { 140 | TabLayout.Tab selectedTab = mTabLayout.getTabAt(2); 141 | if (selectedTab != null) { 142 | selectedTab.setText(t.getTitle()); 143 | } 144 | } 145 | } 146 | 147 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 148 | 149 | @UiThread 150 | public void selectTab( 151 | int tab 152 | ) { 153 | if (mTabLayout != null) { 154 | TabLayout.Tab selectedTab = mTabLayout.getTabAt(tab); 155 | if (selectedTab != null) { 156 | selectedTab.select(); 157 | } 158 | } 159 | } 160 | 161 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 162 | 163 | } 164 | 165 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 166 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/APKMirror/AppExistsRequest.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model.APKMirror; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | public class AppExistsRequest 11 | { 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | public List pnames; 15 | public List exclude; 16 | 17 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | public AppExistsRequest( 20 | List pnames, 21 | List exclude 22 | ) { 23 | this.pnames = pnames; 24 | this.exclude = exclude; 25 | } 26 | 27 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | public static List excludeExperimental( 30 | ) { 31 | List e = new ArrayList<>(); 32 | e.add("alpha"); 33 | e.add("beta"); 34 | e.add("rc"); 35 | e.add("test"); 36 | e.add("other"); 37 | return e; 38 | } 39 | } 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/APKMirror/AppExistsResponse.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model.APKMirror; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import java.util.List; 6 | import com.google.gson.annotations.Expose; 7 | import com.google.gson.annotations.SerializedName; 8 | 9 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | public class AppExistsResponse 12 | { 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | @SerializedName("data") 16 | @Expose 17 | private List data = null; 18 | 19 | @SerializedName("headers") 20 | @Expose 21 | private AppExistsResponseHeaders headers; 22 | 23 | @SerializedName("status") 24 | @Expose 25 | private Integer status; 26 | 27 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | public List getData( 30 | ) { 31 | return data; 32 | } 33 | 34 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | 36 | public void setData( 37 | List data 38 | ) { 39 | this.data = data; 40 | } 41 | 42 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | public AppExistsResponseHeaders getHeaders( 45 | ) { 46 | return headers; 47 | } 48 | 49 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 50 | 51 | public void setHeaders( 52 | AppExistsResponseHeaders headers 53 | ) { 54 | this.headers = headers; 55 | } 56 | 57 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 58 | 59 | public Integer getStatus( 60 | ) { 61 | return status; 62 | } 63 | 64 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 65 | 66 | public void setStatus( 67 | Integer status 68 | ) { 69 | this.status = status; 70 | } 71 | 72 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | } 74 | 75 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/APKMirror/AppExistsResponseApp.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model.APKMirror; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import com.google.gson.annotations.Expose; 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | public class AppExistsResponseApp 11 | { 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | @SerializedName("name") 15 | @Expose 16 | private String name; 17 | 18 | @SerializedName("description") 19 | @Expose 20 | private String description; 21 | 22 | @SerializedName("link") 23 | @Expose 24 | private String link; 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | public String getName( 29 | ) { 30 | return name; 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | 35 | public void setName( 36 | String name 37 | ) { 38 | this.name = name; 39 | } 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | public String getDescription( 44 | ) { 45 | return description; 46 | } 47 | 48 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 49 | 50 | public void setDescription( 51 | String description 52 | ) { 53 | this.description = description; 54 | } 55 | 56 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | 58 | public String getLink( 59 | ) { 60 | return link; 61 | } 62 | 63 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64 | 65 | public void setLink( 66 | String link 67 | ) { 68 | this.link = link; 69 | } 70 | 71 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 72 | 73 | } 74 | 75 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 76 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/APKMirror/AppExistsResponseData.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model.APKMirror; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import java.util.List; 6 | import com.google.gson.annotations.Expose; 7 | import com.google.gson.annotations.SerializedName; 8 | 9 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | public class AppExistsResponseData 12 | { 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | @SerializedName("pname") 16 | @Expose 17 | private String pname; 18 | 19 | @SerializedName("exists") 20 | @Expose 21 | private Boolean exists; 22 | 23 | @SerializedName("developer") 24 | @Expose 25 | private AppExistsResponseDeveloper developer; 26 | 27 | @SerializedName("app") 28 | @Expose 29 | private AppExistsResponseApp app; 30 | 31 | @SerializedName("release") 32 | @Expose 33 | private AppExistsResponseRelease release; 34 | 35 | @SerializedName("apks") 36 | @Expose 37 | private List apks = null; 38 | 39 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | 41 | public String getPname( 42 | ) { 43 | return pname; 44 | } 45 | 46 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 47 | 48 | public void setPname( 49 | String pname 50 | ) { 51 | this.pname = pname; 52 | } 53 | 54 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 55 | 56 | public Boolean getExists( 57 | ) { 58 | return exists; 59 | } 60 | 61 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 62 | 63 | public void setExists( 64 | Boolean exists 65 | ) { 66 | this.exists = exists; 67 | } 68 | 69 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 70 | 71 | public AppExistsResponseDeveloper getDeveloper( 72 | ) { 73 | return developer; 74 | } 75 | 76 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 77 | 78 | public void setDeveloper( 79 | AppExistsResponseDeveloper developer 80 | ) { 81 | this.developer = developer; 82 | } 83 | 84 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 85 | 86 | public AppExistsResponseApp getApp( 87 | ) { 88 | return app; 89 | } 90 | 91 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 92 | 93 | public void setApp( 94 | AppExistsResponseApp app 95 | ) { 96 | this.app = app; 97 | } 98 | 99 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 100 | 101 | public AppExistsResponseRelease getRelease( 102 | ) { 103 | return release; 104 | } 105 | 106 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 107 | 108 | public void setRelease( 109 | AppExistsResponseRelease release 110 | ) { 111 | this.release = release; 112 | } 113 | 114 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 115 | 116 | public List getApks( 117 | ) { 118 | return apks; 119 | } 120 | 121 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 122 | 123 | public void setApks( 124 | List apks 125 | ) { 126 | this.apks = apks; 127 | } 128 | 129 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 130 | } 131 | 132 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/APKMirror/AppExistsResponseDeveloper.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model.APKMirror; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import com.google.gson.annotations.Expose; 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | public class AppExistsResponseDeveloper 11 | { 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | @SerializedName("name") 15 | @Expose 16 | private String name; 17 | 18 | @SerializedName("link") 19 | @Expose 20 | private String link; 21 | 22 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | public String getName( 25 | ) { 26 | return name; 27 | } 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | 31 | public void setName( 32 | String name 33 | ) { 34 | this.name = name; 35 | } 36 | 37 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | public String getLink( 40 | ) { 41 | return link; 42 | } 43 | 44 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | 46 | public void setLink( 47 | String link 48 | ) { 49 | this.link = link; 50 | } 51 | 52 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53 | } 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/APKMirror/AppExistsResponseHeaders.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model.APKMirror; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import com.google.gson.annotations.Expose; 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | public class AppExistsResponseHeaders 11 | { 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | @SerializedName("Allow") 15 | @Expose 16 | private String allow; 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | public String getAllow( 21 | ) { 22 | return allow; 23 | } 24 | 25 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | 27 | public void setAllow( 28 | String allow 29 | ) { 30 | this.allow = allow; 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | } 35 | 36 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/APKMirror/AppExistsResponseRelease.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model.APKMirror; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import com.google.gson.annotations.Expose; 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | public class AppExistsResponseRelease { 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | @SerializedName("version") 15 | @Expose 16 | private String version; 17 | 18 | @SerializedName("publish_date") 19 | @Expose 20 | private String publishDate; 21 | 22 | @SerializedName("whats_new") 23 | @Expose 24 | private String whatsNew; 25 | 26 | @SerializedName("link") 27 | @Expose 28 | private String link; 29 | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | 32 | public String getVersion( 33 | ) { 34 | return version; 35 | } 36 | 37 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | public void setVersion( 40 | String version 41 | ) { 42 | this.version = version; 43 | } 44 | 45 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 46 | 47 | public String getPublishDate( 48 | ) { 49 | return publishDate; 50 | } 51 | 52 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53 | 54 | public void setPublishDate( 55 | String publishDate 56 | ) { 57 | this.publishDate = publishDate; 58 | } 59 | 60 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | 62 | public String getWhatsNew( 63 | ) { 64 | return whatsNew; 65 | } 66 | 67 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 | 69 | public void setWhatsNew( 70 | String whatsNew 71 | ) { 72 | this.whatsNew = whatsNew; 73 | } 74 | 75 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 76 | 77 | public String getLink( 78 | ) { 79 | return link; 80 | } 81 | 82 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 83 | 84 | public void setLink( 85 | String link 86 | ) { 87 | this.link = link; 88 | } 89 | 90 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 91 | } 92 | 93 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/ActionButton.kt: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | class ActionButton(var text: String, var loading: Boolean, var callback: () -> Unit) 6 | 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/Constants.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class Constants 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | static public final String PackageName = "de.apkgrabber"; 10 | static public final String GitHubURL = "https://github.com/hemker/apkgrabber"; 11 | static public final String OwnAccountHelpURL = "https://github.com/rumboalla/apkupdater/issues/223"; 12 | static public final String DownloadAction = PackageName + ".DOWNLOAD_COMPLETE"; 13 | static public final String DownloadManagerAction = "android.intent.action.DOWNLOAD_COMPLETE"; 14 | static public final String FileProvider = PackageName + ".fileprovider"; 15 | static public final String ApkMime = "application/vnd.android.package-archive"; 16 | static public final int UpdaterNotificationId = 42; 17 | static public final int SelfUpdateNotificationId = 42 + 1; 18 | static public final int AutomaticUpdateNotificationId = 42 + 2; 19 | static public final int OwnPlayAccountRequestCode = 42; 20 | static public final String OWN_GSFID_KEY = "own_gsfid_key"; 21 | static public final String OWN_TOKEN_KEY = "oen_token_key"; 22 | static public final String UpdaterNotificationChannelId = "updaterNotificationChannel"; 23 | static public final String SelfUpdaterNotificationChannelId = "selfUpdateNotificationChannel"; 24 | static public final String AutomaticUpdateNotificationChannelId = "automaticUpdateNotificationChannel"; 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | } 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/DownloadInfo.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class DownloadInfo 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private String packageName; 10 | private int versionCode; 11 | private String versionName; 12 | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | public DownloadInfo( 16 | String packageName, 17 | int versionCode, 18 | String versionName 19 | ) { 20 | 21 | this.packageName = packageName; 22 | this.versionCode = versionCode; 23 | this.versionName = versionName; 24 | } 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | public String getPackageName( 29 | ) { 30 | return packageName; 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | 35 | public void setPackagepName( 36 | String packageName 37 | ) { 38 | this.packageName = packageName; 39 | } 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | public int getVersionCode( 44 | ) { 45 | return versionCode; 46 | } 47 | 48 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 49 | 50 | public void setVersionCode( 51 | int versionCode 52 | ) { 53 | this.versionCode = versionCode; 54 | } 55 | 56 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | 58 | public String getVersionName( 59 | ) { 60 | return versionName; 61 | } 62 | 63 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64 | 65 | public void setVersionName( 66 | String versionName 67 | ) { 68 | this.versionName = versionName; 69 | } 70 | 71 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 72 | 73 | } 74 | 75 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/GitHub/Asset.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model.GitHub; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import com.google.gson.annotations.Expose; 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | public class Asset 11 | { 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | @SerializedName("url") 15 | @Expose 16 | private String url; 17 | 18 | @SerializedName("browser_download_url") 19 | @Expose 20 | private String browserDownloadUrl; 21 | 22 | @SerializedName("id") 23 | @Expose 24 | private Integer id; 25 | 26 | @SerializedName("name") 27 | @Expose 28 | private String name; 29 | 30 | @SerializedName("label") 31 | @Expose 32 | private String label; 33 | 34 | @SerializedName("state") 35 | @Expose 36 | private String state; 37 | 38 | @SerializedName("content_type") 39 | @Expose 40 | private String contentType; 41 | 42 | @SerializedName("size") 43 | @Expose 44 | private Integer size; 45 | 46 | @SerializedName("download_count") 47 | @Expose 48 | private Integer downloadCount; 49 | 50 | @SerializedName("created_at") 51 | @Expose 52 | private String createdAt; 53 | 54 | @SerializedName("updated_at") 55 | @Expose 56 | private String updatedAt; 57 | 58 | @SerializedName("uploader") 59 | @Expose 60 | private Uploader uploader; 61 | 62 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 63 | 64 | public String getUrl() { 65 | return url; 66 | } 67 | 68 | public void setUrl(String url) { 69 | this.url = url; 70 | } 71 | 72 | public String getBrowserDownloadUrl() { 73 | return browserDownloadUrl; 74 | } 75 | 76 | public void setBrowserDownloadUrl(String browserDownloadUrl) { 77 | this.browserDownloadUrl = browserDownloadUrl; 78 | } 79 | 80 | public Integer getId() { 81 | return id; 82 | } 83 | 84 | public void setId(Integer id) { 85 | this.id = id; 86 | } 87 | 88 | public String getName() { 89 | return name; 90 | } 91 | 92 | public void setName(String name) { 93 | this.name = name; 94 | } 95 | 96 | public String getLabel() { 97 | return label; 98 | } 99 | 100 | public void setLabel(String label) { 101 | this.label = label; 102 | } 103 | 104 | public String getState() { 105 | return state; 106 | } 107 | 108 | public void setState(String state) { 109 | this.state = state; 110 | } 111 | 112 | public String getContentType() { 113 | return contentType; 114 | } 115 | 116 | public void setContentType(String contentType) { 117 | this.contentType = contentType; 118 | } 119 | 120 | public Integer getSize() { 121 | return size; 122 | } 123 | 124 | public void setSize(Integer size) { 125 | this.size = size; 126 | } 127 | 128 | public Integer getDownloadCount() { 129 | return downloadCount; 130 | } 131 | 132 | public void setDownloadCount(Integer downloadCount) { 133 | this.downloadCount = downloadCount; 134 | } 135 | 136 | public String getCreatedAt() { 137 | return createdAt; 138 | } 139 | 140 | public void setCreatedAt(String createdAt) { 141 | this.createdAt = createdAt; 142 | } 143 | 144 | public String getUpdatedAt() { 145 | return updatedAt; 146 | } 147 | 148 | public void setUpdatedAt(String updatedAt) { 149 | this.updatedAt = updatedAt; 150 | } 151 | 152 | public Uploader getUploader() { 153 | return uploader; 154 | } 155 | 156 | public void setUploader(Uploader uploader) { 157 | this.uploader = uploader; 158 | } 159 | 160 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 161 | 162 | } 163 | 164 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/IgnoreVersion.kt: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | class IgnoreVersion(var packageName: String, var versionName: String, var versionCode: Int) 6 | 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/InstallStatus.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class InstallStatus 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | public static final int STATUS_INSTALL = 0; 10 | public static final int STATUS_INSTALLING = 1; 11 | public static final int STATUS_INSTALLED = 2; 12 | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | private long mId; 16 | private int mStatus; 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | public InstallStatus( 21 | ) { 22 | setId(0); 23 | setStatus(0); 24 | } 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | public InstallStatus( 29 | long id, 30 | int status 31 | ) { 32 | setId(id); 33 | setStatus(status); 34 | } 35 | 36 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 37 | 38 | public int getStatus( 39 | ) { 40 | return mStatus; 41 | } 42 | 43 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | 45 | public long getId( 46 | ) { 47 | return mId; 48 | } 49 | 50 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 51 | 52 | public void setStatus( 53 | int status 54 | ) { 55 | mStatus = status; 56 | } 57 | 58 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | 60 | public void setId( 61 | long id 62 | ) { 63 | mId = id; 64 | } 65 | 66 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 67 | 68 | } 69 | 70 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/InstalledApp.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class InstalledApp 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | private String mName; 10 | private String mPname; 11 | private String mVersion; 12 | private Integer mVersionCode; 13 | private InstallStatus mInstallStatus = new InstallStatus(); 14 | 15 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | 17 | public String getName( 18 | ) { 19 | return mName; 20 | } 21 | 22 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | public void setName( 25 | String mame) { 26 | mName = mame; 27 | } 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | 31 | public String getPname() { 32 | return mPname; 33 | } 34 | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | 37 | public void setPname(String pname) { 38 | mPname = pname; 39 | } 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | public String getVersion() { 44 | return mVersion; 45 | } 46 | 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | 49 | public void setVersion(String version) { 50 | mVersion = version; 51 | } 52 | 53 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | 55 | public Integer getVersionCode( 56 | ) { 57 | return mVersionCode; 58 | } 59 | 60 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | 62 | public void setVersionCode( 63 | Integer mVersionCode 64 | ) { 65 | this.mVersionCode = mVersionCode; 66 | } 67 | 68 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 69 | 70 | public InstallStatus getInstallStatus( 71 | ) { 72 | return mInstallStatus; 73 | } 74 | 75 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 76 | 77 | public void setInstallStatus( 78 | InstallStatus installStatus 79 | ) { 80 | mInstallStatus = installStatus; 81 | } 82 | 83 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 84 | } 85 | 86 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 87 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/LogMessage.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public class LogMessage 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | public static final int SEVERITY_INFO = 0; 10 | public static final int SEVERITY_WARNING = 1; 11 | public static final int SEVERITY_ERROR = 2; 12 | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | private String mTitle; 16 | private String mMessage; 17 | private int mSeverity; 18 | private long mTime; 19 | 20 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | public LogMessage( 23 | String title, 24 | String message, 25 | int severity 26 | ) { 27 | setTitle(title); 28 | setSeverity(severity); 29 | setMessage(message); 30 | mTime = System.currentTimeMillis(); 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | 35 | public String getMessage( 36 | ) { 37 | return mMessage; 38 | } 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | 42 | public long getTime( 43 | ) { 44 | return mTime; 45 | } 46 | 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | 49 | public void setMessage( 50 | String message 51 | ) { 52 | mMessage = message; 53 | } 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | 57 | public int getSeverity( 58 | ) { 59 | return mSeverity; 60 | } 61 | 62 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 63 | 64 | public void setSeverity( 65 | int severity 66 | ) { 67 | mSeverity = severity; 68 | } 69 | 70 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | 72 | public String getTitle( 73 | ) { 74 | return mTitle; 75 | } 76 | 77 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 78 | 79 | public void setTitle( 80 | String title 81 | ) { 82 | mTitle = title; 83 | } 84 | 85 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 86 | 87 | } 88 | 89 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/model/MergedUpdate.kt: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.model 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | class MergedUpdate(var updateList : List) 6 | 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/receiver/AlarmReceiver.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.receiver; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.BroadcastReceiver; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.os.Build; 9 | 10 | import de.apkgrabber.service.UpdaterService; 11 | import de.apkgrabber.service.UpdaterService_; 12 | 13 | import org.androidannotations.annotations.EReceiver; 14 | 15 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | 17 | @EReceiver 18 | public class AlarmReceiver 19 | extends BroadcastReceiver { 20 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | @Override 23 | public void onReceive( 24 | Context context, 25 | Intent intent 26 | ) { 27 | Intent updaterIntent = new Intent(context, UpdaterService_.class).putExtra(UpdaterService.isFromAlarmExtra, true); 28 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 29 | context.startForegroundService(updaterIntent); 30 | } else { 31 | context.startService(updaterIntent); 32 | } 33 | } 34 | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | } 37 | 38 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/receiver/BootReceiver.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.receiver; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.BroadcastReceiver; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | 9 | import de.apkgrabber.util.AlarmUtil; 10 | 11 | import org.androidannotations.annotations.Bean; 12 | import org.androidannotations.annotations.EReceiver; 13 | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | @EReceiver 17 | public class BootReceiver 18 | extends BroadcastReceiver 19 | { 20 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | @Bean 23 | AlarmUtil alarmUtil; 24 | 25 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | 27 | @Override 28 | public void onReceive( 29 | Context context, 30 | Intent intent 31 | ) { 32 | alarmUtil.setAlarmFromOptions(); 33 | } 34 | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | } 37 | 38 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/receiver/NotificationClickReceiver.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.receiver; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.BroadcastReceiver; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | 9 | import de.apkgrabber.activity.MainActivity_; 10 | import de.apkgrabber.model.AppState; 11 | 12 | import org.androidannotations.annotations.Bean; 13 | import org.androidannotations.annotations.EReceiver; 14 | 15 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | 17 | @EReceiver 18 | public class NotificationClickReceiver 19 | extends BroadcastReceiver 20 | { 21 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | @Bean 24 | AppState mAppState; 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | @Override 29 | public void onReceive( 30 | Context context, 31 | Intent intent 32 | ) { 33 | mAppState.setFirstStart(false); 34 | mAppState.setSelectedTab(1); 35 | MainActivity_.intent(context) 36 | .extra("isFromNotification", true) 37 | .flags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP) 38 | .start(); 39 | } 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | } 44 | 45 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/receiver/SelfUpdateNotificationReceiver.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.receiver; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.BroadcastReceiver; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | 9 | import de.apkgrabber.R; 10 | import de.apkgrabber.activity.MainActivity_; 11 | import de.apkgrabber.model.AppState; 12 | import de.apkgrabber.model.DownloadInfo; 13 | import de.apkgrabber.util.DownloadUtil; 14 | 15 | import org.androidannotations.annotations.Bean; 16 | import org.androidannotations.annotations.EReceiver; 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | @EReceiver 21 | public class SelfUpdateNotificationReceiver 22 | extends BroadcastReceiver 23 | { 24 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | @Bean 27 | AppState mAppState; 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | 31 | @Override 32 | public void onReceive( 33 | Context context, 34 | Intent intent 35 | ) { 36 | try { 37 | String url = intent.getStringExtra("url"); 38 | String versionName = intent.getStringExtra("versionName"); 39 | 40 | MainActivity_.intent(context).flags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP).start(); 41 | 42 | String text = String.format("%s %s", context.getString(R.string.app_name), versionName); 43 | long id = DownloadUtil.downloadFile(context, url, "", text); 44 | 45 | // Add to the DownloadInfo 46 | mAppState.getDownloadInfo().put( 47 | id, 48 | new DownloadInfo(context.getPackageName(), 0, versionName) 49 | ); 50 | } catch (Exception e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | 57 | } 58 | 59 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/updater/IUpdater.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.updater; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public interface IUpdater 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | String getResultUrl(); 10 | String getResultCookie(); 11 | int getResultVersionCode(); 12 | Throwable getResultError(); 13 | UpdaterStatus getResultStatus(); 14 | String getResultVersion(); 15 | boolean isBeta(); 16 | 17 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | } 20 | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/updater/UpdaterAPKPure.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.updater; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | 7 | import org.jsoup.Jsoup; 8 | import org.jsoup.nodes.Document; 9 | import org.jsoup.select.Elements; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public class UpdaterAPKPure 14 | extends UpdaterBase 15 | { 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | static final private String BaseUrl = "https://apkpure.com"; 19 | static final private String Type = "APKPure"; 20 | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | public UpdaterAPKPure( 24 | Context context, 25 | String pname, 26 | String cversion 27 | ) { 28 | super(context, pname, cversion, "APKPure"); 29 | } 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | @Override 34 | protected String getUrl( 35 | String pname 36 | ) { 37 | return BaseUrl + "/search?q=" + pname; 38 | } 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | 42 | @Override 43 | protected UpdaterStatus parseUrl( 44 | String url 45 | ) { 46 | try { 47 | Document doc = Jsoup.connect(url).get(); 48 | 49 | // Search for URL ending on / + package name 50 | Elements elements = doc.getElementsByAttributeValueEnding("href", "/" + mPname); 51 | if(elements == null || elements.size() == 0) { 52 | return UpdaterStatus.STATUS_UPDATE_NOT_FOUND; 53 | } 54 | 55 | // Build new url to request 56 | url = BaseUrl + elements.get(0).attr("href"); 57 | doc = Jsoup.connect(url).get(); 58 | 59 | // Try to get the version 60 | //elements = doc.getElementsByAttributeValue("itemprop", "softwareVersion"); 61 | elements = doc.getElementsByClass("version-ul").get(0).getElementsByTag("p"); 62 | if(elements == null || elements.size() == 0) { 63 | return UpdaterStatus.STATUS_UPDATE_NOT_FOUND; 64 | } 65 | 66 | // If version is old, report update 67 | if (compareVersions(mCurrentVersion, elements.get(3).text()) == -1) { 68 | mResultUrl = url; 69 | mResultVersion = elements.get(3).text(); 70 | return UpdaterStatus.STATUS_UPDATE_FOUND; 71 | } 72 | 73 | return UpdaterStatus.STATUS_UPDATE_NOT_FOUND; 74 | } catch (Exception e) { 75 | mError = addCommonInfoToError(e); 76 | return UpdaterStatus.STATUS_ERROR; 77 | } 78 | } 79 | 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | } 82 | 83 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/updater/UpdaterAptoide.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.updater; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | 7 | import com.fasterxml.jackson.databind.JsonNode; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | 10 | import java.io.IOException; 11 | import java.net.HttpURLConnection; 12 | import java.net.URL; 13 | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | public class UpdaterAptoide 17 | extends UpdaterBase { 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | static final private String BaseUrl = "https://ws75.aptoide.com"; 21 | static final private String Type = "Aptoide"; 22 | 23 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | 25 | public UpdaterAptoide( 26 | Context context, 27 | String pname, 28 | String cversion 29 | ) { 30 | super(context, pname, cversion, Type); 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | 35 | @Override 36 | protected String getUrl( 37 | String pname 38 | ) { 39 | return BaseUrl + "/api/7/app/get/package_name=" + pname; 40 | } 41 | 42 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | @Override 45 | protected UpdaterStatus parseUrl( 46 | String url 47 | ) { 48 | try { 49 | final ObjectMapper mapper = new ObjectMapper(); 50 | final JsonNode root = mapper.readTree(new URL(url)); 51 | 52 | if (root.get("info").get("status").asText().equals("OK")) { 53 | final JsonNode file = root.get("nodes").get("meta").get("data").get("file"); 54 | final String versionName = file.get("vername").asText(); 55 | final int versionCode = file.get("vercode").asInt(); 56 | final String apkDownloadUrl = file.get("path").asText(); 57 | 58 | if (compareVersions(mCurrentVersion, versionName) == -1) { 59 | mResultUrl = apkDownloadUrl; 60 | mResultVersion = versionName; 61 | mResultVersionCode = versionCode; 62 | return UpdaterStatus.STATUS_UPDATE_FOUND; 63 | } 64 | } 65 | } catch (Exception e) { 66 | if(appExists(url)) { 67 | mError = addCommonInfoToError(e); 68 | return UpdaterStatus.STATUS_ERROR; 69 | } 70 | } 71 | 72 | return UpdaterStatus.STATUS_UPDATE_NOT_FOUND; 73 | } 74 | 75 | private boolean appExists(String url) { 76 | try { 77 | URL url2Check = new URL(url); 78 | HttpURLConnection connection = (HttpURLConnection) url2Check.openConnection(); 79 | connection.setRequestMethod("GET"); 80 | connection.connect(); 81 | return connection.getResponseCode() == HttpURLConnection.HTTP_OK; 82 | } catch (IOException e) { 83 | return false; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/updater/UpdaterBase.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.updater; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | 7 | import de.apkgrabber.util.VersionUtil; 8 | 9 | import java.util.List; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public class UpdaterBase 14 | extends UpdaterOptions 15 | implements IUpdater 16 | { 17 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | protected String mPname; 20 | protected String mUrl; 21 | protected String mResultUrl; 22 | protected String mResultVersion; 23 | protected int mResultVersionCode; 24 | protected Throwable mError; 25 | protected UpdaterStatus mResultStatus; 26 | protected String mCurrentVersion; 27 | protected String mUpdaterType; 28 | protected boolean mIsBeta; 29 | protected String mResultCookie; 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | UpdaterBase( 34 | Context context, 35 | String pname, 36 | String cversion, 37 | String type 38 | ) { 39 | super(context); 40 | mCurrentVersion = cversion; 41 | mResultUrl = ""; 42 | mPname = pname; 43 | mUpdaterType = type; 44 | mIsBeta = false; 45 | mResultStatus = parseUrl(getUrl(mPname)); 46 | } 47 | 48 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 49 | 50 | protected String getUrl( 51 | String pname 52 | ) { 53 | return mUrl; 54 | } 55 | 56 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | 58 | protected UpdaterStatus parseUrl( 59 | String url 60 | ) { 61 | return UpdaterStatus.STATUS_FATAL_ERROR; 62 | } 63 | 64 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 65 | 66 | protected Throwable addCommonInfoToError( 67 | Throwable error 68 | ) { 69 | return new Exception(error.getMessage() == null ? "" : error.getMessage() + " | App: " + mPname + " | Source: " + mUpdaterType); 70 | } 71 | 72 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | 74 | protected int compareVersions( 75 | String cv, 76 | String ev 77 | ) 78 | throws Exception 79 | { 80 | List cvl = VersionUtil.getVersionFromString(cv); 81 | if (cvl == null) { 82 | throw new Exception("Unable to parse version: " + cv); 83 | } 84 | 85 | List evl = VersionUtil.getVersionFromString(ev); 86 | if (evl == null) { 87 | throw new Exception("Unable to parse version: " + ev); 88 | } 89 | 90 | return VersionUtil.compareVersion(cvl, evl); 91 | } 92 | 93 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 94 | 95 | @Override 96 | public String getResultUrl( 97 | ) { 98 | return mResultUrl; 99 | } 100 | 101 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 102 | 103 | @Override 104 | public Throwable getResultError( 105 | ) { 106 | return mError; 107 | } 108 | 109 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 110 | 111 | @Override 112 | public UpdaterStatus getResultStatus( 113 | ) { 114 | return mResultStatus; 115 | } 116 | 117 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 118 | 119 | @Override 120 | public String getResultVersion( 121 | ) { 122 | return mResultVersion; 123 | } 124 | 125 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 126 | 127 | @Override 128 | public boolean isBeta( 129 | ) { 130 | return mIsBeta; 131 | } 132 | 133 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 134 | 135 | @Override 136 | public String getResultCookie( 137 | ) { 138 | return mResultCookie; 139 | } 140 | 141 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 142 | 143 | @Override 144 | public int getResultVersionCode( 145 | ) { 146 | return mResultVersionCode; 147 | } 148 | 149 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 150 | 151 | } 152 | 153 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 154 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/updater/UpdaterCallback.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.updater; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import de.apkgrabber.model.Update; 6 | 7 | interface UpdaterCallback 8 | { 9 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | void onStart(); 12 | void onUpdate(Update update); 13 | void onError(Throwable e); 14 | void onFinish(String m); 15 | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | } 18 | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/updater/UpdaterStatus.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.updater; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public enum UpdaterStatus 6 | { 7 | STATUS_UPDATE_FOUND, 8 | STATUS_UPDATE_NOT_FOUND, 9 | STATUS_ERROR, 10 | STATUS_FATAL_ERROR 11 | } 12 | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/updater/UpdaterUptodown.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.updater; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | 7 | import org.jsoup.HttpStatusException; 8 | import org.jsoup.Jsoup; 9 | import org.jsoup.nodes.Document; 10 | import org.jsoup.select.Elements; 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | public class UpdaterUptodown 15 | extends UpdaterBase 16 | { 17 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | static final private String BaseUrl = "http://en.uptodown.com/android/"; 20 | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | public UpdaterUptodown( 24 | Context context, 25 | String pname, 26 | String cversion 27 | ) { 28 | super(context, pname, cversion, "Uptodown"); 29 | } 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | @Override 34 | protected String getUrl( 35 | String pname 36 | ) { 37 | return BaseUrl + "search/" + pname.replace(".", "-"); 38 | } 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | 42 | @Override 43 | protected UpdaterStatus parseUrl( 44 | String url 45 | ) { 46 | try { 47 | Document doc = Jsoup.connect(url).get(); 48 | 49 | for (int i = 0; i < 20; i++) { 50 | // Get the url for the first app returned 51 | Elements elements = doc.getElementsByClass("cardlink_1_" + i); 52 | if (elements.size() < 1) { 53 | return UpdaterStatus.STATUS_UPDATE_NOT_FOUND; 54 | } 55 | String app_url = elements.get(0).attr("href"); 56 | 57 | // Get package name from app url 58 | Document doc2 = Jsoup.connect(app_url).get(); 59 | elements = doc2.getElementsByClass("packagename"); 60 | if (elements.size() < 1) { 61 | return UpdaterStatus.STATUS_UPDATE_NOT_FOUND; 62 | } 63 | String pname = elements.get(0).getElementsByClass("right").get(0).html(); 64 | 65 | // Check if it's the same app 66 | if (!pname.equals(mPname)) { 67 | continue; 68 | } 69 | 70 | // Get version 71 | String version = doc2.getElementsByAttributeValue("itemprop", "softwareVersion").get(0).html(); 72 | 73 | // Compare versions 74 | if (compareVersions(mCurrentVersion, version) == -1) { 75 | mResultUrl = app_url; 76 | mResultVersion = version; 77 | return UpdaterStatus.STATUS_UPDATE_FOUND; 78 | } 79 | } 80 | 81 | return UpdaterStatus.STATUS_UPDATE_NOT_FOUND; 82 | } catch (HttpStatusException status) { 83 | if (status.getStatusCode() == 404 || status.getStatusCode() == 403) { 84 | return UpdaterStatus.STATUS_UPDATE_NOT_FOUND; 85 | } else { 86 | mError = addCommonInfoToError(status); 87 | return UpdaterStatus.STATUS_ERROR; 88 | } 89 | } catch (Exception e) { 90 | mError = addCommonInfoToError(e); 91 | return UpdaterStatus.STATUS_ERROR; 92 | } 93 | } 94 | 95 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 96 | } 97 | 98 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 99 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/AlarmUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.app.AlarmManager; 6 | import android.app.PendingIntent; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | 10 | import de.apkgrabber.R; 11 | import de.apkgrabber.receiver.AlarmReceiver_; 12 | import de.apkgrabber.updater.UpdaterOptions; 13 | 14 | import org.androidannotations.annotations.EBean; 15 | 16 | import java.util.Calendar; 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | @EBean(scope = EBean.Scope.Singleton) 21 | public class AlarmUtil 22 | { 23 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | 25 | AlarmManager alarmManager; 26 | PendingIntent alarmIntent; 27 | Context mContext; 28 | Long mRescheduleTimeInMilis = 900000L; 29 | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | 32 | public AlarmUtil( 33 | Context context 34 | ) { 35 | mContext = context; 36 | 37 | // Get the alarm manager 38 | alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 39 | 40 | // Create the pending intent that will be called by the alarm 41 | Intent intent = new Intent(context, AlarmReceiver_.class); 42 | intent.setAction("de.apkgrabber.alarm"); 43 | alarmIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 44 | } 45 | 46 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 47 | 48 | public void setAlarmFromOptions( 49 | ) { 50 | UpdaterOptions options = new UpdaterOptions(mContext); 51 | String alarm = options.getAlarmOption(); 52 | long interval; 53 | 54 | if (alarm.equals(mContext.getString(R.string.alarm_daily))) { 55 | interval = AlarmManager.INTERVAL_DAY; 56 | } else if (alarm.equals(mContext.getString(R.string.alarm_weekly))) { 57 | interval = AlarmManager.INTERVAL_DAY * 7; 58 | } else { 59 | cancelAlarm(); 60 | return; 61 | } 62 | 63 | setAlarm(interval); 64 | } 65 | 66 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 67 | 68 | public void setAlarm( 69 | long interval 70 | ) { 71 | // Get update hour from options 72 | int hour = 12; 73 | try { 74 | UpdaterOptions options = new UpdaterOptions(mContext); 75 | String time = options.getUpdateHour(); 76 | String [] split = time.split(":"); 77 | hour = Integer.valueOf(split[0]); 78 | } catch (Exception e) { 79 | e.printStackTrace(); 80 | } 81 | 82 | // Configure the alarm 83 | Calendar calendar = Calendar.getInstance(); 84 | calendar.setTimeInMillis(System.currentTimeMillis()); 85 | calendar.set(Calendar.HOUR_OF_DAY, hour); 86 | calendar.set(Calendar.MINUTE, 0); 87 | if (calendar.getTimeInMillis() < System.currentTimeMillis() // Add a day if alarm is in the past 88 | || Calendar.getInstance().get(Calendar.HOUR_OF_DAY) == hour // Add a day if we are setting an alarm for the current hour 89 | ) { 90 | calendar.add(Calendar.DAY_OF_MONTH, 1); 91 | } 92 | alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), interval, alarmIntent); 93 | } 94 | 95 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 96 | 97 | public void rescheduleAlarm( 98 | ) { 99 | alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + mRescheduleTimeInMilis, alarmIntent); 100 | } 101 | 102 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 103 | 104 | public void cancelAlarm( 105 | ) { 106 | alarmManager.cancel(alarmIntent); 107 | } 108 | 109 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 110 | } 111 | 112 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/AnimationUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.support.transition.AutoTransition; 8 | import android.transition.ChangeBounds; 9 | import android.transition.Fade; 10 | import android.transition.Slide; 11 | import android.transition.TransitionManager; 12 | import android.transition.TransitionSet; 13 | import android.view.Gravity; 14 | import android.view.ViewGroup; 15 | 16 | import de.apkgrabber.updater.UpdaterOptions; 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | public class AnimationUtil 21 | { 22 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | public static void startDefaultAnimation( 25 | Context context, 26 | ViewGroup v 27 | ) { 28 | if (new UpdaterOptions(context).disableAnimations()) { 29 | // No animation 30 | } else if (Build.VERSION.SDK_INT >= 21) { 31 | TransitionManager.beginDelayedTransition(v); 32 | } else if (Build.VERSION.SDK_INT >= 14){ 33 | android.support.transition.TransitionManager.beginDelayedTransition(v); 34 | } { 35 | // No animation 36 | } 37 | } 38 | 39 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | 41 | public static void startSlideAnimation( 42 | Context context, 43 | ViewGroup v 44 | ) { 45 | if (new UpdaterOptions(context).disableAnimations()) { 46 | // No animation 47 | } else if (Build.VERSION.SDK_INT >= 21) { 48 | TransitionManager.beginDelayedTransition(v, new Slide()); 49 | } else if (Build.VERSION.SDK_INT >= 14){ 50 | android.support.transition.TransitionManager.beginDelayedTransition(v); // Support v26 will add Slide 51 | } { 52 | // No animation 53 | } 54 | } 55 | 56 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | 58 | public static void startToolbarAnimation( 59 | Context context, 60 | ViewGroup v 61 | ) { 62 | if (new UpdaterOptions(context).disableAnimations()) { 63 | return; 64 | } 65 | 66 | if (Build.VERSION.SDK_INT >= 21) { 67 | TransitionManager.beginDelayedTransition(v, new TransitionSet() 68 | .addTransition(new Fade(Fade.IN)) 69 | .addTransition(new Slide(Gravity.LEFT)) 70 | .addTransition(new ChangeBounds()) 71 | ); 72 | 73 | } else if (Build.VERSION.SDK_INT >= 14){ 74 | android.support.transition.TransitionManager.beginDelayedTransition(v, new AutoTransition().setDuration(250)); 75 | } { 76 | // No animation 77 | } 78 | } 79 | 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | 82 | } 83 | 84 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 85 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/CollectionUtil.kt: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import de.apkgrabber.model.APKMirror.AppExistsResponseApk 6 | 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | class CollectionUtil 10 | { 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | companion object 14 | { 15 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | 17 | fun sortAppExistsResponseApk( 18 | list : List 19 | ) : List { 20 | try { 21 | return list.sortedWith( 22 | compareByDescending { it.minapi } 23 | .thenByDescending { it.dpis[0] } 24 | .thenByDescending { it.arches[0] } 25 | ) 26 | } catch (e : Exception) { 27 | return list 28 | } 29 | } 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | fun getFirstAppExistResponse( 34 | list : List 35 | ) : AppExistsResponseApk { 36 | return list.firstOrNull { it.dpis[0] != "nodpi"} ?: list.first() 37 | } 38 | 39 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | } 41 | 42 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | } 45 | 46 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/ColorUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.content.res.Resources; 7 | import android.content.res.TypedArray; 8 | import android.graphics.drawable.Drawable; 9 | import android.support.v4.graphics.drawable.DrawableCompat; 10 | import android.util.TypedValue; 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | public class ColorUtil { 15 | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | public static int getColorFromTheme( 19 | Resources.Theme theme, 20 | int color_id 21 | ) { 22 | TypedValue typedValue = new TypedValue(); 23 | theme.resolveAttribute(color_id, typedValue, true); 24 | return typedValue.data; 25 | } 26 | 27 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | public static int getColorFromContext( 30 | Context context, 31 | int color_id 32 | ) { 33 | int[] textSizeAttr = new int[] {color_id }; 34 | TypedValue typedValue = new TypedValue(); 35 | TypedArray a = context.obtainStyledAttributes(typedValue.data, textSizeAttr); 36 | int color = a.getColor(0, 0); 37 | a.recycle(); 38 | return color; 39 | } 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | public static String getHexStringFromInt( 44 | int color 45 | ) { 46 | return "#" + String.format("%06X", 0xFFFFFF & color); 47 | } 48 | 49 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 50 | 51 | public static Drawable tintDrawable( 52 | Context context, 53 | Drawable icon, 54 | int resColor 55 | ) { 56 | DrawableCompat.setTint(DrawableCompat.wrap(icon), ColorUtil.getColorFromContext(context, resColor)); 57 | return icon; 58 | } 59 | 60 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | } 62 | 63 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.os.Environment; 7 | 8 | import java.io.File; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | import java.util.UUID; 14 | 15 | import eu.chainfire.libsuperuser.Shell; 16 | 17 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | public class FileUtil 20 | { 21 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | static public boolean inputStreamToFile( 24 | InputStream input, 25 | File file 26 | ) { 27 | try { 28 | OutputStream output = new FileOutputStream(file); 29 | byte[] buffer = new byte[4096]; 30 | int read; 31 | 32 | while ((read = input.read(buffer)) != -1) { 33 | output.write(buffer, 0, read); 34 | } 35 | 36 | output.flush(); 37 | output.close(); 38 | input.close(); 39 | 40 | return true; 41 | } catch (Exception e) { 42 | return false; 43 | } 44 | } 45 | 46 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 47 | 48 | static public boolean installApk( 49 | String path 50 | ) 51 | throws Exception 52 | { 53 | if (Shell.SU.available()) { 54 | if(Shell.SU.run("pm install -r " + path) == null) { 55 | throw new Exception("Error executing pm install."); 56 | } else { 57 | return true; 58 | } 59 | } else { 60 | throw new Exception("Root not available."); 61 | } 62 | } 63 | 64 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 65 | 66 | static public File getRandomFile( 67 | Context context 68 | ) 69 | throws IOException 70 | { 71 | File dir = context.getExternalCacheDir(); 72 | if (dir == null) { 73 | // if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 74 | // throw new IOException("No external storage."); 75 | // } 76 | 77 | dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); 78 | 79 | if (dir == null) { 80 | throw new IOException("Unable to get file."); 81 | } 82 | } 83 | return new File(dir, UUID.randomUUID().toString()); 84 | } 85 | 86 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 87 | 88 | } 89 | 90 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/GenericCallback.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | public interface GenericCallback 6 | { 7 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | void onResult(T t); 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | } 13 | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/GooglePlayUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.util.Pair; 7 | 8 | import de.apkgrabber.updater.UpdaterOptions; 9 | import de.apkgrabber.util.yalp.NativeDeviceInfoProvider; 10 | import de.apkgrabber.util.yalp.OkHttpClientAdapter; 11 | import com.github.yeriomin.playstoreapi.AndroidAppDeliveryData; 12 | import com.github.yeriomin.playstoreapi.DeviceInfoProvider; 13 | import com.github.yeriomin.playstoreapi.DocV2; 14 | import com.github.yeriomin.playstoreapi.GooglePlayAPI; 15 | 16 | import java.io.IOException; 17 | import java.util.Locale; 18 | import java.util.Random; 19 | 20 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | public class GooglePlayUtil 23 | { 24 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | private static final String [] GSFID = { 27 | "326b94da1d625a12", 28 | "3e2d9529d52d8d6c", 29 | "3321ca20a1b56509", 30 | "35b1905948d34f68", 31 | "3205280df61a4644" 32 | }; 33 | 34 | private static final String [] TOKEN = { 35 | "2ATSi286IOTP_2vbf7m6uNSmqzdsWiWcRmqmNwOYrrZs0jnTyNwyB4wn204qHHldlle_Qg.", 36 | "2AR9Nn0xfO-gHRigTZVBTrrwNPtebofzYssA9q2SH_c1q7W8S8rDkfpUg0KO--3ArHbuIQ.", 37 | "2AQgOEr9h_Wb8lp4isUymIJYJrz4TDHZ-zrZyHlcr0hmTbuOD4pVd1TrpO-iNhf9ntiuSw.", 38 | "2AS4jUFSPpP-UHmruqWnOyKVdNaE9GsYa1NV9EZJHgkWvfSVa-0WwepqTczdBoPM3HL3CQ.", 39 | "1gTCN_ouDuqbAVg7UViJL5tJ00m7Pc061nEWsf8SLQdE0bCIkhrqp6rUSikdxEaJA9sGCQ." 40 | }; 41 | 42 | private static int i = getCounter(); 43 | 44 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | 46 | static public GooglePlayAPI getApi( 47 | Context context 48 | ) { 49 | GooglePlayAPI api = null; 50 | int c = 0; 51 | 52 | while (api == null && c < 10) { 53 | try { 54 | 55 | 56 | com.github.yeriomin.playstoreapi.PlayStoreApiBuilder builder = new com.github.yeriomin.playstoreapi.PlayStoreApiBuilder() 57 | .setHttpClient(new OkHttpClientAdapter()) 58 | .setDeviceInfoProvider(getNativeProvider(context)) 59 | .setLocale(Locale.getDefault()) 60 | .setEmail(null) 61 | .setPassword(null); 62 | 63 | UpdaterOptions options = new UpdaterOptions(context); 64 | if (options.useOwnPlayAccount()) { 65 | builder.setGsfId(options.getOwnGsfId()).setToken(options.getOwnToken()); 66 | } else { 67 | builder.setGsfId(GSFID[i]).setToken(TOKEN[i]); 68 | } 69 | 70 | api = builder.build(); 71 | api.uploadDeviceConfig(); 72 | } catch (Exception e) { 73 | api = null; 74 | i = getCounter(); 75 | } finally { 76 | c++; 77 | } 78 | } 79 | 80 | return api; 81 | } 82 | 83 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 84 | 85 | public static DeviceInfoProvider getNativeProvider( 86 | Context context 87 | ) { 88 | DeviceInfoProvider deviceInfoProvider = new NativeDeviceInfoProvider(); 89 | ((NativeDeviceInfoProvider) deviceInfoProvider).setContext(context); 90 | ((NativeDeviceInfoProvider) deviceInfoProvider).setLocaleString(Locale.getDefault().toString()); 91 | return deviceInfoProvider; 92 | } 93 | 94 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 95 | 96 | public static AndroidAppDeliveryData getAppDeliveryData( 97 | GooglePlayAPI api, 98 | String pname 99 | ) throws IOException { 100 | DocV2 d = api.details(pname).getDocV2(); 101 | return api.purchase( 102 | d.getDetails().getAppDetails().getPackageName(), 103 | d.getDetails().getAppDetails().getVersionCode(), 104 | d.getOffer(0).getOfferType() 105 | ).getPurchaseStatusResponse().getAppDeliveryData(); 106 | } 107 | 108 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 109 | 110 | public static Pair getIdTokenPairFromEmailPassword( 111 | Context context, 112 | String email, 113 | String password 114 | ) throws Exception { 115 | 116 | com.github.yeriomin.playstoreapi.PlayStoreApiBuilder builder = new com.github.yeriomin.playstoreapi.PlayStoreApiBuilder() 117 | .setHttpClient(new OkHttpClientAdapter()) 118 | .setDeviceInfoProvider(getNativeProvider(context)) 119 | .setLocale(Locale.getDefault()) 120 | .setEmail(email) 121 | .setPassword(password); 122 | 123 | GooglePlayAPI api = builder.build(); 124 | return new Pair<>(api.getGsfId(), api.getToken()); 125 | } 126 | 127 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 128 | 129 | private static int getCounter( 130 | ) { 131 | return new Random().nextInt(GSFID.length); 132 | } 133 | 134 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 135 | } 136 | 137 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/InjektUtil.kt: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import de.apkgrabber.activity.MainActivity 6 | import de.apkgrabber.adapter.UpdaterAdapter 7 | import de.apkgrabber.model.AppState 8 | import uy.kohesive.injekt.api.InjektScope 9 | import uy.kohesive.injekt.api.addSingleton 10 | import uy.kohesive.injekt.registry.default.DefaultRegistrar 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | class InjektUtil 15 | { 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | companion object 19 | { 20 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | var injekt : InjektScope? = null 23 | 24 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | fun init( 27 | ) { 28 | injekt = InjektScope(DefaultRegistrar()) 29 | } 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | fun addAppStateSingleton( 34 | appState : AppState 35 | ) { 36 | injekt?.addSingleton(appState) 37 | } 38 | 39 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | 41 | fun addMyBusSingleton( 42 | bus : MyBus 43 | ) { 44 | injekt?.addSingleton(bus) 45 | } 46 | 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | 49 | fun addLogUtilSingleton( 50 | logger : LogUtil 51 | ) { 52 | injekt?.addSingleton(logger) 53 | } 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | 57 | fun addActivitySingleton( 58 | activity : MainActivity 59 | ) { 60 | injekt?.addSingleton(activity) 61 | } 62 | 63 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64 | 65 | fun addUpdaterAdapterSingleton( 66 | adapter : UpdaterAdapter 67 | ) { 68 | injekt?.addSingleton(adapter) 69 | } 70 | 71 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 72 | } 73 | 74 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 75 | } 76 | 77 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/LogUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | import de.apkgrabber.model.LogMessage; 4 | 5 | import org.androidannotations.annotations.Bean; 6 | import org.androidannotations.annotations.EBean; 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | @EBean(scope = EBean.Scope.Singleton) 11 | public class LogUtil 12 | { 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | @Bean 16 | MyBus mBus; 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | public void log( 21 | String title, 22 | String message, 23 | int severity 24 | ) { 25 | mBus.post(new LogMessage(title, message, severity)); 26 | } 27 | 28 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | } 30 | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/MyBus.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | 8 | import com.squareup.otto.Bus; 9 | 10 | import org.androidannotations.annotations.EBean; 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | @EBean(scope = EBean.Scope.Singleton) 15 | public class MyBus 16 | extends Bus 17 | { 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | private final Handler mHandler = new Handler(Looper.getMainLooper()); 21 | 22 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | @Override 25 | public void post( 26 | final Object event 27 | ) { 28 | if (Looper.myLooper() == Looper.getMainLooper()) { 29 | super.post(event); 30 | } else { 31 | mHandler.post(new Runnable() { 32 | @Override 33 | public void run() { 34 | MyBus.super.post(event); 35 | } 36 | }); 37 | } 38 | } 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | 42 | } 43 | 44 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/NotificationHelper.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | import android.app.NotificationChannel; 4 | import android.app.NotificationManager; 5 | import android.content.Context; 6 | import android.graphics.Color; 7 | import android.os.Build; 8 | 9 | public class NotificationHelper { 10 | 11 | public static void createNotificationChannel(String id, String name, String description, Context context) { 12 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 13 | NotificationChannel channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_DEFAULT); 14 | channel.setDescription(description); 15 | channel.enableLights(true); 16 | channel.setLightColor(Color.RED); 17 | channel.setVibrationPattern(new long[]{100}); 18 | ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)) 19 | .createNotificationChannel(channel); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/PixelConversion.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.content.res.Resources; 7 | import android.util.DisplayMetrics; 8 | 9 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | public class PixelConversion 12 | { 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | public static float convertDpToPixel( 16 | float dp, 17 | Context context 18 | ){ 19 | Resources resources = context.getResources(); 20 | DisplayMetrics metrics = resources.getDisplayMetrics(); 21 | return dp * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); 22 | } 23 | 24 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | public static float convertPixelsToDp( 27 | float px, 28 | Context context 29 | ){ 30 | Resources resources = context.getResources(); 31 | DisplayMetrics metrics = resources.getDisplayMetrics(); 32 | return px / ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); 33 | } 34 | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | 37 | } 38 | 39 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/ServiceUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.app.ActivityManager; 6 | import android.content.Context; 7 | import android.net.ConnectivityManager; 8 | import android.net.NetworkInfo; 9 | 10 | import java.util.List; 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | public class ServiceUtil 15 | { 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | public static boolean isServiceRunning( 19 | Context context, 20 | Class serviceClass 21 | ) { 22 | ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 23 | List t = manager.getRunningServices(Integer.MAX_VALUE); 24 | for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 25 | if (serviceClass.getName().equals(service.service.getClassName())) { 26 | return true; 27 | } 28 | } 29 | return false; 30 | } 31 | 32 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | 34 | public static boolean isConnected( 35 | Context context 36 | ) { 37 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 38 | NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 39 | return activeNetwork != null && activeNetwork.isConnectedOrConnecting(); 40 | } 41 | 42 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | public static boolean isWifi( 45 | Context context 46 | ) { 47 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 48 | NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 49 | return activeNetwork.getType() == ConnectivityManager.TYPE_WIFI; 50 | } 51 | 52 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53 | } 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/SnackBarUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.app.Activity; 6 | import android.support.design.widget.Snackbar; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | 10 | import de.apkgrabber.R; 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | public class SnackBarUtil { 15 | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | static public void make( 19 | Activity activity, 20 | String text 21 | ) { 22 | try { 23 | if (text == null || text.isEmpty() || activity == null) { 24 | return; 25 | } 26 | 27 | final Snackbar bar = Snackbar.make(activity.findViewById(R.id.main_content), text, Snackbar.LENGTH_LONG); 28 | bar.setAction(activity.getString(R.string.snackbar_close), new View.OnClickListener() { 29 | @Override 30 | public void onClick(View view) { 31 | bar.dismiss(); 32 | } 33 | }).show(); 34 | View view = bar.getView(); 35 | view.setBackgroundColor(ColorUtil.getColorFromTheme(activity.getTheme(), R.attr.colorPrimary)); 36 | TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text); 37 | tv.setTextColor(ColorUtil.getColorFromContext(activity, android.R.attr.textColorPrimary)); 38 | } catch (NullPointerException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | 43 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | } 45 | 46 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 47 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/ThemeUtil.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | 7 | import de.apkgrabber.R; 8 | import de.apkgrabber.updater.UpdaterOptions; 9 | 10 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | 12 | public class ThemeUtil 13 | { 14 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | public static int getActivityThemeFromOptions( 17 | Context context 18 | ) { 19 | String theme = new UpdaterOptions(context).getTheme(); 20 | if(theme.equals(context.getString(R.string.theme_blue))) { 21 | return R.style.AppThemeBlue; 22 | } else if (theme.equals(context.getString(R.string.theme_dark))) { 23 | return R.style.AppThemeDark; 24 | } else if (theme.equals(context.getString(R.string.theme_pink))) { 25 | return R.style.AppThemePink; 26 | } else if (theme.equals(context.getString(R.string.theme_orange))) { 27 | return R.style.AppThemeOrange; 28 | } else if (theme.equals(context.getString(R.string.theme_bloody))) { 29 | return R.style.AppThemeBloody; 30 | } else if (theme.equals(context.getString(R.string.theme_amoled))) { 31 | return R.style.AppThemeAmoled; 32 | } else { 33 | return R.style.AppThemeBlue; 34 | } 35 | } 36 | 37 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | public static int getSettingsThemeFromOptions( 40 | Context context 41 | ) { 42 | String theme = new UpdaterOptions(context).getTheme(); 43 | if(theme.equals(context.getString(R.string.theme_blue))) { 44 | return R.style.PreferenceThemeBlue; 45 | } else if (theme.equals(context.getString(R.string.theme_dark))) { 46 | return R.style.PreferenceThemeDark; 47 | } else if (theme.equals(context.getString(R.string.theme_pink))) { 48 | return R.style.PreferenceThemePink; 49 | }else if (theme.equals(context.getString(R.string.theme_orange))) { 50 | return R.style.PreferenceThemeOrange; 51 | } else if (theme.equals(context.getString(R.string.theme_bloody))) { 52 | return R.style.PreferenceThemeBloody; 53 | } else if (theme.equals(context.getString(R.string.theme_amoled))) { 54 | return R.style.PreferenceThemeAmoled; 55 | } else { 56 | return R.style.PreferenceThemeBlue; 57 | } 58 | } 59 | 60 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | 62 | public static int getCardBackgroundColor( 63 | Context context 64 | ) { 65 | String theme = new UpdaterOptions(context).getTheme(); 66 | if(theme.equals(context.getString(R.string.theme_blue))) { 67 | return 0xFFFFFFFF; 68 | } else if (theme.equals(context.getString(R.string.theme_dark))) { 69 | return 0xFF424242; 70 | } else if (theme.equals(context.getString(R.string.theme_pink))) { 71 | return 0xFF424242; 72 | }else if (theme.equals(context.getString(R.string.theme_orange))) { 73 | return 0xFFFFFFFF; 74 | } else if (theme.equals(context.getString(R.string.theme_bloody))) { 75 | return 0; 76 | } else if (theme.equals(context.getString(R.string.theme_amoled))) { 77 | return 0; 78 | } else { 79 | return 0xFFFFFFFF; 80 | } 81 | } 82 | 83 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 84 | } 85 | 86 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 87 | -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/util/yalp/EglExtensionRetriever.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.util.yalp; 2 | 3 | import android.opengl.GLES10; 4 | import android.text.TextUtils; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.HashSet; 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | import javax.microedition.khronos.egl.EGL10; 13 | import javax.microedition.khronos.egl.EGLConfig; 14 | import javax.microedition.khronos.egl.EGLContext; 15 | import javax.microedition.khronos.egl.EGLDisplay; 16 | 17 | public class EglExtensionRetriever { 18 | 19 | public static List getEglExtensions() { 20 | Set glExtensions = new HashSet<>(); 21 | EGL10 egl10 = (EGL10) EGLContext.getEGL(); 22 | if (egl10 == null) { 23 | return new ArrayList<>(); 24 | } 25 | EGLDisplay display = egl10.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 26 | egl10.eglInitialize(display, new int[2]); 27 | int cf[] = new int[1]; 28 | if (egl10.eglGetConfigs(display, null, 0, cf)) { 29 | EGLConfig[] configs = new EGLConfig[cf[0]]; 30 | if (egl10.eglGetConfigs(display, configs, cf[0], cf)) { 31 | int[] a1 = new int[] {EGL10.EGL_WIDTH, EGL10.EGL_PBUFFER_BIT, EGL10.EGL_HEIGHT, EGL10.EGL_PBUFFER_BIT, EGL10.EGL_NONE}; 32 | int[] a2 = new int[] {12440, EGL10.EGL_PIXMAP_BIT, EGL10.EGL_NONE}; 33 | int[] a3 = new int[1]; 34 | for (int i = 0; i < cf[0]; i++) { 35 | egl10.eglGetConfigAttrib(display, configs[i], EGL10.EGL_CONFIG_CAVEAT, a3); 36 | if (a3[0] != EGL10.EGL_SLOW_CONFIG) { 37 | egl10.eglGetConfigAttrib(display, configs[i], EGL10.EGL_SURFACE_TYPE, a3); 38 | if ((1 & a3[0]) != 0) { 39 | egl10.eglGetConfigAttrib(display, configs[i], EGL10.EGL_RENDERABLE_TYPE, a3); 40 | if ((1 & a3[0]) != 0) { 41 | addExtensionsForConfig(egl10, display, configs[i], a1, null, glExtensions); 42 | } 43 | if ((4 & a3[0]) != 0) { 44 | addExtensionsForConfig(egl10, display, configs[i], a1, a2, glExtensions); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | egl10.eglTerminate(display); 52 | List sorted = new ArrayList<>(glExtensions); 53 | Collections.sort(sorted); 54 | return sorted; 55 | } 56 | 57 | private static void addExtensionsForConfig(EGL10 egl10, EGLDisplay egldisplay, EGLConfig eglconfig, int ai[], int ai1[], Set set) { 58 | EGLContext eglContext = egl10.eglCreateContext(egldisplay, eglconfig, EGL10.EGL_NO_CONTEXT, ai1); 59 | if (eglContext == EGL10.EGL_NO_CONTEXT) { 60 | return; 61 | } 62 | javax.microedition.khronos.egl.EGLSurface eglSurface = egl10.eglCreatePbufferSurface(egldisplay, eglconfig, ai); 63 | if (eglSurface == EGL10.EGL_NO_SURFACE) { 64 | egl10.eglDestroyContext(egldisplay, eglContext); 65 | } else { 66 | egl10.eglMakeCurrent(egldisplay, eglSurface, eglSurface, eglContext); 67 | String s = GLES10.glGetString(7939); 68 | if (!TextUtils.isEmpty(s)) { 69 | String as[] = s.split(" "); 70 | int i = as.length; 71 | for (int j = 0; j < i; j++) { 72 | set.add(as[j]); 73 | } 74 | } 75 | egl10.eglMakeCurrent(egldisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 76 | egl10.eglDestroySurface(egldisplay, eglSurface); 77 | egl10.eglDestroyContext(egldisplay, eglContext); 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/view/CustomCardView.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.view; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.support.v7.widget.CardView; 7 | import android.util.AttributeSet; 8 | 9 | import de.apkgrabber.util.ThemeUtil; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public class CustomCardView 14 | extends CardView 15 | { 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | public CustomCardView(Context context) { 19 | super(context); 20 | setCardBackgroundColor(ThemeUtil.getCardBackgroundColor(context)); 21 | } 22 | 23 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | 25 | public CustomCardView(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | setCardBackgroundColor(ThemeUtil.getCardBackgroundColor(context)); 28 | } 29 | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | 32 | public CustomCardView(Context context, AttributeSet attrs, int defStyleAttr) { 33 | super(context, attrs, defStyleAttr); 34 | setCardBackgroundColor(ThemeUtil.getCardBackgroundColor(context)); 35 | } 36 | 37 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | } 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/view/CustomViewPager.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.view; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.support.v4.view.ViewPager; 7 | import android.util.AttributeSet; 8 | 9 | import de.apkgrabber.updater.UpdaterOptions; 10 | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | public class CustomViewPager 14 | extends ViewPager 15 | { 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | public CustomViewPager( 19 | Context context 20 | ) { 21 | super(context); 22 | } 23 | 24 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | public CustomViewPager( 27 | Context context, 28 | AttributeSet attrs 29 | ) { 30 | super(context, attrs); 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | 35 | @Override 36 | public void setCurrentItem( 37 | int item, 38 | boolean smoothScroll 39 | ) { 40 | super.setCurrentItem(item, !new UpdaterOptions(getContext()).disableAnimations()); 41 | } 42 | 43 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | 45 | @Override 46 | public void setCurrentItem( 47 | int item 48 | ) { 49 | super.setCurrentItem(item, !new UpdaterOptions(getContext()).disableAnimations()); 50 | } 51 | 52 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53 | } 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/view/LogView.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.view; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.support.v4.content.ContextCompat; 7 | import android.widget.ImageView; 8 | import android.widget.LinearLayout; 9 | import android.widget.TextView; 10 | 11 | import de.apkgrabber.R; 12 | import de.apkgrabber.model.LogMessage; 13 | 14 | import org.androidannotations.annotations.EViewGroup; 15 | import org.androidannotations.annotations.ViewById; 16 | 17 | import java.text.DateFormat; 18 | import java.text.SimpleDateFormat; 19 | import java.util.Date; 20 | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | @EViewGroup(R.layout.log_item) 24 | public class LogView 25 | extends LinearLayout 26 | { 27 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | @ViewById(R.id.log_title) 30 | TextView mTitle; 31 | 32 | @ViewById(R.id.log_time) 33 | TextView mTime; 34 | 35 | @ViewById(R.id.log_message) 36 | TextView mMessage; 37 | 38 | @ViewById(R.id.log_icon) 39 | ImageView mIcon; 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | public LogView( 44 | Context context 45 | ) { 46 | super(context); 47 | } 48 | 49 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 50 | 51 | public void bind( 52 | LogMessage message 53 | ) { 54 | mTitle.setText(message.getTitle()); 55 | mMessage.setText(message.getMessage()); 56 | 57 | DateFormat df = SimpleDateFormat.getDateTimeInstance(); 58 | mTime.setText(df.format(new Date(message.getTime()))); 59 | 60 | if (message.getSeverity() == LogMessage.SEVERITY_INFO) { 61 | mIcon.setImageResource(R.drawable.ic_info); 62 | mIcon.setColorFilter(ContextCompat.getColor(getContext(), R.color.infoColor)); 63 | } else if (message.getSeverity() == LogMessage.SEVERITY_WARNING) { 64 | mIcon.setImageResource(R.drawable.ic_warning); 65 | mIcon.setColorFilter(ContextCompat.getColor(getContext(), R.color.warningColor)); 66 | } else if (message.getSeverity() == LogMessage.SEVERITY_ERROR) { 67 | mIcon.setImageResource(R.drawable.ic_error); 68 | mIcon.setColorFilter(ContextCompat.getColor(getContext(), R.color.errorColor)); 69 | } 70 | } 71 | 72 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | } 74 | 75 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/java/de/apkgrabber/view/UpdaterView.java: -------------------------------------------------------------------------------- 1 | package de.apkgrabber.view; 2 | 3 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.graphics.drawable.Drawable; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.ImageView; 11 | import android.widget.LinearLayout; 12 | import android.widget.TextView; 13 | 14 | import de.apkgrabber.R; 15 | import de.apkgrabber.model.Update; 16 | 17 | import org.androidannotations.annotations.EViewGroup; 18 | import org.androidannotations.annotations.ViewById; 19 | 20 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | @EViewGroup(R.layout.updater_item) 23 | public class UpdaterView 24 | extends LinearLayout 25 | { 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | @ViewById(R.id.installed_app_name) 29 | TextView mName; 30 | 31 | @ViewById(R.id.installed_app_pname) 32 | TextView mPname; 33 | 34 | @ViewById(R.id.installed_app_version) 35 | TextView mVersion; 36 | 37 | @ViewById(R.id.installed_app_icon) 38 | ImageView mIcon; 39 | 40 | @ViewById(R.id.update_url) 41 | TextView mUrl; 42 | 43 | @ViewById(R.id.action_one_button) 44 | Button mActionOneButton; 45 | 46 | @ViewById(R.id.action_two_button) 47 | Button mActionTwoButton; 48 | 49 | Context mContext; 50 | 51 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | 53 | public UpdaterView( 54 | Context context 55 | ) { 56 | super(context); 57 | mContext = context; 58 | } 59 | 60 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | 62 | public void bind( 63 | Update update 64 | ) { 65 | mName.setText(update.getName()); 66 | mPname.setText(update.getPname()); 67 | 68 | // Build version string with both old and new version 69 | String version = update.getVersion(); 70 | if (update.getNewVersion() != null && !update.getNewVersion().isEmpty()) { 71 | version += " -> " + update.getNewVersion(); 72 | } 73 | 74 | mVersion.setText(version); 75 | 76 | // Build string for first action 77 | String action = ""; 78 | if (update.getUrl().contains("apkmirror.com")) { 79 | action = mContext.getString(R.string.action_apkmirror); 80 | } else if (update.getUrl().contains("uptodown.com")) { 81 | action = mContext.getString(R.string.action_uptodown); 82 | } else if (update.getUrl().contains("apkpure.com")) { 83 | action = mContext.getString(R.string.action_apkpure); 84 | } else if(update.getUrl().contains("aptoide.com")) { 85 | action = mContext.getString(R.string.action_aptoide); 86 | } 87 | 88 | mActionOneButton.setText(action); 89 | 90 | try { 91 | Drawable icon = getContext().getPackageManager().getApplicationIcon(update.getPname()); 92 | mIcon.setImageDrawable(icon); 93 | } catch (PackageManager.NameNotFoundException ignored) {} 94 | } 95 | 96 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 97 | 98 | public void setActionOneButtonListener( 99 | View.OnClickListener listener 100 | ) { 101 | mActionOneButton.setOnClickListener(listener); 102 | } 103 | 104 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 105 | 106 | public void setActionTwoButtonListener( 107 | View.OnClickListener listener 108 | ) { 109 | mActionTwoButton.setOnClickListener(listener); 110 | } 111 | 112 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 113 | } 114 | 115 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hemker/apkgrabber/6aa67ecda8555a84bffe7f5a8c364d568a536185/app/src/main/res/drawable/banner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_android.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_beta.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_error.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_log.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_update.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_warning.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 17 | 24 | 25 | 31 | 32 | 33 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/layout/button_bar_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 |