Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5200a33b authored by Romain Hunault's avatar Romain Hunault 💻
Browse files

Merge branch 'dev' into 'master'

[RELEASE] Sprint JJ

See merge request e/apps/apps!12
parents 480fc25d e0241951
Loading
Loading
Loading
Loading
Loading
+46 −13
Original line number Diff line number Diff line
@@ -5,14 +5,16 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 27
    compileSdkVersion 28
    buildToolsVersion '28.0.3'
    defaultConfig {
        applicationId "foundation.e.apps"
        minSdkVersion 21
        targetSdkVersion 27
        versionCode 9
        versionCode 10
        versionName "1.1.6"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        aaptOptions.cruncherEnabled = false
    }
    buildTypes {
        release {
@@ -25,28 +27,59 @@ android {
    }
    lintOptions {
        lintConfig file("lint.xml")
        disable 'MissingTranslation'
    }
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }

    androidExtensions {
        experimental = true
    }
}

dependencies {
    def lifecycle_version = "1.1.1"
    implementation "android.arch.work:work-runtime:1.0.1"
    implementation 'androidx.work:work-runtime:2.3.1'
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:design:27.1.1'
    implementation 'com.android.support:preference-v7:27.1.1'
    implementation 'com.android.support:recyclerview-v7:27.1.1'
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    implementation "com.android.support:support-compat:27.1.1"
    implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
//    implementation 'com.android.support:design:27.1.1'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation files('libs/jackson-databind-2.9.7.jar')
    implementation files('libs/jackson-annotations-2.9.7.jar')
    implementation files('libs/jackson-core-2.9.7.jar')
    implementation group: 'commons-codec', name: 'commons-codec', version: '1.11'
    implementation 'org.bouncycastle:bcprov-jdk15on:1.60'
    implementation 'org.bouncycastle:bcpg-jdk15on:1.60'

    implementation "androidx.vectordrawable:vectordrawable:1.0.0"
    implementation "androidx.vectordrawable:vectordrawable-animated:1.0.0"
    implementation 'com.google.android.material:material:1.1.0-alpha05'

    def nav_version = "1.0.0-alpha02"
    implementation 'androidx.navigation:navigation-fragment-ktx:2.0.0-rc02'
// use -ktx for Kotlin
    implementation 'androidx.navigation:navigation-ui-ktx:2.0.0-rc02'

    implementation "androidx.preference:preference-ktx:1.1.0"

    implementation 'androidx.lifecycle:lifecycle-viewmodel:2.0.0'



    implementation 'com.google.code.gson:gson:2.8.2'
    implementation 'com.google.android.material:material:1.0.0'
    implementation 'com.mikepenz:iconics-core:3.1.0@aar'
    implementation 'com.mikepenz:google-material-typeface:3.0.1.2.original@aar'
    implementation 'org.greenrobot:eventbus:3.1.1'

    implementation 'com.trello.rxlifecycle3:rxlifecycle-android:3.1.0'
    implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'
    implementation 'com.trello.rxlifecycle3:rxlifecycle-components-preference:3.1.0'
    implementation 'com.makeramen:roundedimageview:2.3.0'

}

app/manifest.json

0 → 100644
+0 −0

Empty file added.

+18 −2
Original line number Diff line number Diff line
@@ -9,6 +9,9 @@
    <uses-permission
        android:name="android.permission.INSTALL_PACKAGES"
        tools:ignore="ProtectedPermissions" />
    <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
    <uses-permission android:name="com.google.android.launcher.permission.READ_SETTINGS"/>
    <uses-permission android:name="com.google.android.launcher.permission.WRITE_SETTINGS"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -19,8 +22,11 @@
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher"
        android:supportsRtl="true"
        android:largeHeap="true"
        android:launchMode="singleTask"
        android:theme="@style/AppTheme">
        <activity android:name=".settings.AppRequestActivity"></activity>
<!--        <activity android:name=".application.PwaInstaller"/>-->
        <activity android:name=".settings.AppRequestActivity" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
@@ -31,13 +37,14 @@
        <activity android:name=".application.ApplicationActivity" />
        <activity android:name=".categories.category.CategoryActivity" />


        <service
            android:name=".applicationmanager.ApplicationManagerService"
            android:description="@string/service_description"
            android:exported="false" />

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:name="androidx.core.content.FileProvider"
            android:authorities="foundation.e.apps.provider"
            android:exported="false"
            android:grantUriPermissions="true">
@@ -50,6 +57,15 @@
        <activity
            android:name=".application.ScreenshotsActivity"
            android:theme="@style/FullScreenTheme" />
        <activity
            android:name=".PWA.PwaInstaller"
            android:theme="@style/FullScreenTheme" />
        <activity
            android:name=".XAPK.InstallSplitApksActivity"
            android:configChanges="screenSize|orientation|keyboardHidden"
            android:label="XAPK Installer"
            android:launchMode="singleTask"
            android:windowSoftInputMode="adjustResize" />
    </application>

</manifest>
 No newline at end of file
+88 −14
Original line number Diff line number Diff line
@@ -17,16 +17,22 @@

package foundation.e.apps

//import androidx.fragment.app.ListFragment
import android.annotation.SuppressLint
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Bundle
import android.support.design.internal.BottomNavigationItemView
import android.support.design.internal.BottomNavigationMenuView
import android.support.design.widget.BottomNavigationView
import android.support.design.widget.Snackbar
import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import android.os.Handler
import android.preference.PreferenceManager
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.google.android.material.bottomnavigation.BottomNavigationItemView
import com.google.android.material.bottomnavigation.BottomNavigationMenuView
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomnavigation.LabelVisibilityMode
import com.google.android.material.snackbar.Snackbar
import foundation.e.apps.applicationmanager.ApplicationManager
import foundation.e.apps.applicationmanager.ApplicationManagerServiceConnection
import foundation.e.apps.applicationmanager.ApplicationManagerServiceConnectionCallback
@@ -40,24 +46,48 @@ import foundation.e.apps.utils.Constants
import foundation.e.apps.utils.Constants.CURRENTLY_SELECTED_FRAGMENT_KEY
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener,
        ApplicationManagerServiceConnectionCallback {

    private var currentFragmentId = 0
    private val homeFragment = HomeFragment()
    private val searchFragment = SearchFragment()
    private val updatesFragment = UpdatesFragment()
    private val applicationManagerServiceConnection =
            ApplicationManagerServiceConnection(this)
    private val codeRequestPermissions = 9527
    var doubleBackToExitPressedOnce = false;



    companion object {
        lateinit var mActivity: MainActivity
        var sharedPreferences : SharedPreferences?=null
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mActivity = this
        disableCategoryIfOpenSource()


        bottom_navigation_view.setOnNavigationItemSelectedListener{
            if (selectFragment(it.itemId,it)) {
                disableCategoryIfOpenSource()
                currentFragmentId = it.itemId
                return@setOnNavigationItemSelectedListener true
            }
            return@setOnNavigationItemSelectedListener false
        }

        bottom_navigation_view.setOnNavigationItemSelectedListener(this)
        disableShiftingOfNabBarItems()

        initialiseUpdatesWorker()


        // Show the home fragment by default
        currentFragmentId = if (savedInstanceState != null &&
                savedInstanceState.containsKey(CURRENTLY_SELECTED_FRAGMENT_KEY)) {
@@ -73,11 +103,13 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS

    private fun initialiseUpdatesWorker() {
        UpdatesManager(applicationContext).startWorker()


    }

    override fun onServiceBind(applicationManager: ApplicationManager) {
        initialiseFragments(applicationManager)
        selectFragment(currentFragmentId)
        selectFragment(currentFragmentId, null)
    }

    private fun initialiseFragments(applicationManager: ApplicationManager) {
@@ -87,32 +119,53 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        if (selectFragment(item.itemId)) {
        if (selectFragment(item.itemId,item)) {
            currentFragmentId = item.itemId
            return true
        }
        return false
    }

    private fun selectFragment(fragmentId: Int): Boolean {
    fun showApplicationTypePreference(): String {
        val preferences = PreferenceManager.getDefaultSharedPreferences(mActivity)
        var showAllApps = preferences.getBoolean(mActivity.getString(R.string.Show_all_apps), true)
        var showAllOpenSourceApps = preferences.getBoolean(mActivity.getString(R.string.show_only_open_source_apps_key), false)
        var showAllPwaApps = preferences.getBoolean(mActivity.getString(R.string.show_only_pwa_apps_key), false)
        if (showAllOpenSourceApps) {
            return "open"
        } else if (showAllApps) {
            return "any"
        } else if (showAllPwaApps) {
            return "pwa"
        }
        return "any"
    }


    private fun selectFragment(fragmentId: Int, item: MenuItem?): Boolean {
        when (fragmentId) {
            R.id.menu_home -> {
                item?.setIcon(R.drawable.ic_menu_home)
                showFragment(homeFragment)
                return true
            }
            R.id.menu_categories -> {
                item?.setIcon(R.drawable.ic_menu_categories)
                showFragment(CategoriesFragment())
                return true
            }
            R.id.menu_search -> {
                item?.setIcon(R.drawable.ic_menu_search)
                showFragment(searchFragment)
                return true
            }
            R.id.menu_updates -> {
                item?.setIcon(R.drawable.ic_menu_updates)
                showFragment(updatesFragment)
                return true
            }
            R.id.menu_settings -> {
                item?.setIcon(R.drawable.ic_menu_settings)
                showFragment(SettingsFragment())
                return true
            }
@@ -144,8 +197,13 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS

        for (i in 0 until menuView.childCount) {
            val itemView = menuView.getChildAt(i) as BottomNavigationItemView
            itemView.setShiftingMode(false)
            itemView.setChecked(itemView.itemData.isChecked)
            itemView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);            itemView.setChecked(itemView.itemData.isChecked)
        }
    }

    private fun disableCategoryIfOpenSource(){
        if(showApplicationTypePreference()=="open") {
            bottom_navigation_view.menu.removeItem(R.id.menu_categories)
        }
    }

@@ -158,7 +216,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
        }
    }

    override fun onSaveInstanceState(outState: Bundle?) {
    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState?.putInt(CURRENTLY_SELECTED_FRAGMENT_KEY, currentFragmentId)
    }
@@ -170,4 +228,20 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
        updatesFragment.decrementApplicationUses()
        applicationManagerServiceConnection.unbindService(this)
    }

    override fun onBackPressed() {
        if (doubleBackToExitPressedOnce) {
            super.onBackPressed()
            return
        }

        this.doubleBackToExitPressedOnce = true;
        Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();

        Handler().postDelayed(Runnable() {
            run {
                doubleBackToExitPressedOnce = false;
            }
        }, 2000)
    }
}
 No newline at end of file
+136 −0
Original line number Diff line number Diff line
package foundation.e.apps.PWA

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.Icon
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Looper
import android.provider.Browser
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import foundation.e.apps.MainActivity.Companion.mActivity
import foundation.e.apps.MainActivity.Companion.sharedPreferences
import foundation.e.apps.R
import foundation.e.apps.application.model.data.PwasBasicData
import foundation.e.apps.utils.Constants
import java.io.FileNotFoundException
import java.net.URL
import java.util.*
import javax.net.ssl.HttpsURLConnection

class PwaInstaller : AppCompatActivity() {

    var icon : Bitmap?=null
    private val sharedPrefFile = "kotlinsharedpreference"
    var scaledBitmap :Bitmap?=null


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_application)
        sharedPreferences= this.getSharedPreferences(sharedPrefFile,Context.MODE_PRIVATE)


        val extras = intent.extras
        val name = extras.getString("NAME")
        val Url = Uri.parse(extras.getString("URL"))
        installer(name,Url)
    }

    override fun onResume() {
        super.onResume()
        finish()
    }

    fun setBooleanConfig(key:String?,flag:Boolean){
        val editor:SharedPreferences.Editor =  sharedPreferences!!.edit()
        editor.putBoolean(key,flag)
        editor.apply()
    }


    private fun installer(name: String?, myUrl: Uri) {
        setBooleanConfig(name,true)
        Thread{
            run {
                    Looper.prepare();//Call looper.prepare()
                try {
                    var uri = PwasBasicData.thisActivity!!.uri
                    val url = URL(Constants.BASE_URL + "media/" + uri)
                    val urlConnection = url.openConnection() as HttpsURLConnection
                    urlConnection.requestMethod = Constants.REQUEST_METHOD_GET
                    urlConnection.connectTimeout = Constants.CONNECT_TIMEOUT
                    urlConnection.readTimeout = Constants.READ_TIMEOUT
                    icon = BitmapFactory.decodeStream(urlConnection.inputStream)
                    scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true)
                }catch (e: FileNotFoundException) {
                    val x = R.drawable.pwa_default_icon
                    val icon = BitmapFactory.decodeResource(mActivity.getResources(),
                            x)
                    scaledBitmap = Bitmap.createScaledBitmap(icon, 128, 128, true)
                }
                    val intent = Intent()
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    intent.setAction(Intent.ACTION_VIEW)
                    intent.putExtra(Browser.EXTRA_APPLICATION_ID, Long.toString())
                    intent.setData(myUrl)

                    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
                        val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java)


                        if (isExistShortcutInfo(name)) {
                            Toast.makeText(this, "Shortcut already exist", Toast.LENGTH_SHORT).show()
                        } else {
                            Toast.makeText(this, "Shortcut created", Toast.LENGTH_SHORT).show()
                            val shortcut = ShortcutInfo.Builder(mActivity, java.lang.Long.toString(Random().nextLong()))
                                    .setShortLabel(name.toString())
                                    .setIcon(Icon.createWithAdaptiveBitmap(scaledBitmap))
                                    .setIntent(intent)
                                    .build()
                            @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
                            shortcutManager.requestPinShortcut(shortcut, null)
                        }
                    } else {
                        val installer = Intent()
                        installer.putExtra("android.intent.extra.shortcut.INTENT", intent)
                        installer.putExtra("android.intent.extra.shortcut.NAME", name)
                        installer.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaledBitmap)
                        installer.putExtra("duplicate", false);
                        installer.setAction("com.android.launcher.action.INSTALL_SHORTCUT")
                        mActivity.sendBroadcast(installer)
                    }
                Looper.loop();
            }
        }.start()
    }

    companion object {

        @SuppressLint("NewApi")
        fun isExistShortcutInfo(shortcutId: String?): Boolean {
            val shortcutManager = mActivity.getSystemService(ShortcutManager::class.java)

            val shortcutInfoList = shortcutManager!!.getPinnedShortcuts()

            for (info in shortcutInfoList) {
                if (info.getId() == shortcutId) {

                }
                if (info.getShortLabel() == shortcutId) {
                    return true
                }
            }
            return false
        }
    }
}
Loading