Loading app/build.gradle +2 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ android { dependencies { def lifecycle_version = "1.1.1" def work_version = "1.0.0-beta01" implementation "android.arch.work:work-runtime:$work_version" implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support:appcompat-v7:27.1.1' Loading app/src/main/java/io/eelo/appinstaller/MainActivity.kt +18 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ import android.support.design.widget.Snackbar import android.support.v4.app.Fragment import android.support.v7.app.AppCompatActivity import android.view.MenuItem import androidx.work.* import io.eelo.appinstaller.applicationmanager.ApplicationManager import io.eelo.appinstaller.applicationmanager.ApplicationManagerServiceConnection import io.eelo.appinstaller.applicationmanager.ApplicationManagerServiceConnectionCallback Loading @@ -18,9 +19,11 @@ import io.eelo.appinstaller.home.HomeFragment import io.eelo.appinstaller.search.SearchFragment import io.eelo.appinstaller.settings.SettingsFragment import io.eelo.appinstaller.updates.UpdatesFragment import io.eelo.appinstaller.updates.model.UpdatesWorker import io.eelo.appinstaller.utils.Constants import io.eelo.appinstaller.utils.Constants.CURRENTLY_SELECTED_FRAGMENT_KEY import kotlinx.android.synthetic.main.activity_main.* import java.util.concurrent.TimeUnit class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener, ApplicationManagerServiceConnectionCallback { Loading @@ -38,6 +41,8 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS bottom_navigation_view.setOnNavigationItemSelectedListener(this) disableShiftingOfNabBarItems() initialiseUpdatesWorker() // Show the home fragment by default currentFragmentId = if (savedInstanceState != null && savedInstanceState.containsKey(CURRENTLY_SELECTED_FRAGMENT_KEY)) { Loading @@ -49,6 +54,19 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS applicationManagerServiceConnection.bindService(this) } private fun initialiseUpdatesWorker() { val constraints = Constraints.Builder().apply { setRequiresBatteryNotLow(true) setRequiredNetworkType(NetworkType.CONNECTED) }.build() val updatesCheckBuilder = PeriodicWorkRequest .Builder(UpdatesWorker::class.java, 15, TimeUnit.MINUTES).apply { setConstraints(constraints) } WorkManager.getInstance().enqueueUniquePeriodicWork(Constants.UPDATES_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, updatesCheckBuilder.build()) } override fun onServiceBind(applicationManager: ApplicationManager) { initialiseFragments(applicationManager) selectFragment(currentFragmentId) Loading app/src/main/java/io/eelo/appinstaller/application/model/Application.kt +7 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,13 @@ class Application(val packageName: String, private val applicationManager: Appli return uses.get() != 0 } fun assertBasicData(context: Context): Error? { if (basicData != null) { return null } return findBasicData(context) } fun assertFullData(context: Context): Error? { if (fullData != null) { return null Loading app/src/main/java/io/eelo/appinstaller/updates/UpdatesFragment.kt +33 −14 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ import android.widget.LinearLayout import android.widget.ProgressBar import android.widget.TextView import io.eelo.appinstaller.R import io.eelo.appinstaller.application.model.Application import io.eelo.appinstaller.applicationmanager.ApplicationManager import io.eelo.appinstaller.common.ApplicationListAdapter import io.eelo.appinstaller.updates.viewModel.UpdatesViewModel Loading @@ -22,6 +23,7 @@ class UpdatesFragment : Fragment() { private lateinit var updatesViewModel: UpdatesViewModel private var applicationManager: ApplicationManager? = null private lateinit var recyclerView: RecyclerView private var applicationList = ArrayList<Application>() fun initialise(applicationManager: ApplicationManager) { this.applicationManager = applicationManager Loading @@ -36,25 +38,42 @@ class UpdatesFragment : Fragment() { updatesViewModel = ViewModelProviders.of(activity!!).get(UpdatesViewModel::class.java) recyclerView = view.findViewById(R.id.app_list) val splashContainer = view.findViewById<LinearLayout>(R.id.splash_container) val progressBar = view.findViewById<ProgressBar>(R.id.progress_bar) val errorContainer = view.findViewById<LinearLayout>(R.id.error_container) val errorDescription = view.findViewById<TextView>(R.id.error_description) // Initialise UI elements updatesViewModel.initialise(applicationManager!!) initializeRecyclerView() recyclerView.visibility = View.GONE progressBar.visibility = View.VISIBLE errorContainer.visibility = View.GONE splashContainer.visibility = View.GONE view.findViewById<TextView>(R.id.error_resolve).setOnClickListener { progressBar.visibility = View.VISIBLE updatesViewModel.loadApplicationList(context!!) } // Bind recycler view adapter to search results list in view model // Initialise recycler view recyclerView.setHasFixedSize(true) recyclerView.layoutManager = LinearLayoutManager(context) recyclerView.adapter = ApplicationListAdapter(activity!!, applicationList) // Bind recycler view adapter to outdated applications list in view model updatesViewModel.getApplications().observe(this, Observer { if (it!!.isNotEmpty()) { recyclerView.adapter.notifyDataSetChanged() if (it != null) { applicationList.clear() applicationList.addAll(it) progressBar.visibility = View.GONE recyclerView.adapter.notifyDataSetChanged() recyclerView.scrollToPosition(0) if (applicationList.isEmpty()) { recyclerView.visibility = View.GONE splashContainer.visibility = View.VISIBLE } else { splashContainer.visibility = View.GONE recyclerView.visibility = View.VISIBLE } } }) Loading @@ -64,6 +83,8 @@ class UpdatesFragment : Fragment() { errorDescription.text = activity!!.getString(Common.getScreenErrorDescriptionId(it)) errorContainer.visibility = View.VISIBLE progressBar.visibility = View.GONE splashContainer.visibility = View.GONE recyclerView.visibility = View.GONE } else { errorContainer.visibility = View.GONE } Loading @@ -74,25 +95,23 @@ class UpdatesFragment : Fragment() { return view } private fun initializeRecyclerView() { recyclerView.setHasFixedSize(true) recyclerView.layoutManager = LinearLayoutManager(context) recyclerView.adapter = ApplicationListAdapter(activity!!, updatesViewModel.getApplications().value!!) } override fun onResume() { super.onResume() if (::updatesViewModel.isInitialized) { updatesViewModel.getApplications().value!!.forEach { application -> updatesViewModel.getApplications().value?.let { it.forEach { application -> application.checkForStateUpdate(context!!) } } } } fun decrementApplicationUses() { if (::updatesViewModel.isInitialized) { updatesViewModel.getApplications().value!!.forEach { it.decrementUses() updatesViewModel.getApplications().value?.let { it.forEach { application -> application.decrementUses() } } } } Loading app/src/main/java/io/eelo/appinstaller/updates/model/OutdatedApplicationsFileReader.kt 0 → 100644 +44 −0 Original line number Diff line number Diff line package io.eelo.appinstaller.updates.model import android.content.Context import android.os.AsyncTask import io.eelo.appinstaller.application.model.Application import io.eelo.appinstaller.application.model.State import io.eelo.appinstaller.applicationmanager.ApplicationManager import io.eelo.appinstaller.utils.Constants import java.io.BufferedReader import java.io.InputStreamReader import java.lang.Exception class OutdatedApplicationsFileReader(private val applicationManager: ApplicationManager, private val callback: UpdatesModelInterface) : AsyncTask<Context, Void, ArrayList<Application>>() { override fun doInBackground(vararg context: Context): ArrayList<Application> { val applications = ArrayList<Application>() try { context[0].openFileInput(Constants.OUTDATED_APPLICATIONS_FILENAME).use { val inputStreamReader = InputStreamReader(it) val bufferedReader = BufferedReader(inputStreamReader) bufferedReader.forEachLine { packageName -> val application = applicationManager.findOrCreateApp(packageName) val error = application.assertBasicData(context[0]) if (error == null) { if (application.state == State.NOT_UPDATED) { applications.add(application) } } } bufferedReader.close() inputStreamReader.close() it.close() } } catch (exception: Exception) { exception.printStackTrace() } return applications } override fun onPostExecute(result: ArrayList<Application>) { callback.onAppsFound(result) } } Loading
app/build.gradle +2 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ android { dependencies { def lifecycle_version = "1.1.1" def work_version = "1.0.0-beta01" implementation "android.arch.work:work-runtime:$work_version" implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support:appcompat-v7:27.1.1' Loading
app/src/main/java/io/eelo/appinstaller/MainActivity.kt +18 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ import android.support.design.widget.Snackbar import android.support.v4.app.Fragment import android.support.v7.app.AppCompatActivity import android.view.MenuItem import androidx.work.* import io.eelo.appinstaller.applicationmanager.ApplicationManager import io.eelo.appinstaller.applicationmanager.ApplicationManagerServiceConnection import io.eelo.appinstaller.applicationmanager.ApplicationManagerServiceConnectionCallback Loading @@ -18,9 +19,11 @@ import io.eelo.appinstaller.home.HomeFragment import io.eelo.appinstaller.search.SearchFragment import io.eelo.appinstaller.settings.SettingsFragment import io.eelo.appinstaller.updates.UpdatesFragment import io.eelo.appinstaller.updates.model.UpdatesWorker import io.eelo.appinstaller.utils.Constants import io.eelo.appinstaller.utils.Constants.CURRENTLY_SELECTED_FRAGMENT_KEY import kotlinx.android.synthetic.main.activity_main.* import java.util.concurrent.TimeUnit class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener, ApplicationManagerServiceConnectionCallback { Loading @@ -38,6 +41,8 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS bottom_navigation_view.setOnNavigationItemSelectedListener(this) disableShiftingOfNabBarItems() initialiseUpdatesWorker() // Show the home fragment by default currentFragmentId = if (savedInstanceState != null && savedInstanceState.containsKey(CURRENTLY_SELECTED_FRAGMENT_KEY)) { Loading @@ -49,6 +54,19 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS applicationManagerServiceConnection.bindService(this) } private fun initialiseUpdatesWorker() { val constraints = Constraints.Builder().apply { setRequiresBatteryNotLow(true) setRequiredNetworkType(NetworkType.CONNECTED) }.build() val updatesCheckBuilder = PeriodicWorkRequest .Builder(UpdatesWorker::class.java, 15, TimeUnit.MINUTES).apply { setConstraints(constraints) } WorkManager.getInstance().enqueueUniquePeriodicWork(Constants.UPDATES_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, updatesCheckBuilder.build()) } override fun onServiceBind(applicationManager: ApplicationManager) { initialiseFragments(applicationManager) selectFragment(currentFragmentId) Loading
app/src/main/java/io/eelo/appinstaller/application/model/Application.kt +7 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,13 @@ class Application(val packageName: String, private val applicationManager: Appli return uses.get() != 0 } fun assertBasicData(context: Context): Error? { if (basicData != null) { return null } return findBasicData(context) } fun assertFullData(context: Context): Error? { if (fullData != null) { return null Loading
app/src/main/java/io/eelo/appinstaller/updates/UpdatesFragment.kt +33 −14 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ import android.widget.LinearLayout import android.widget.ProgressBar import android.widget.TextView import io.eelo.appinstaller.R import io.eelo.appinstaller.application.model.Application import io.eelo.appinstaller.applicationmanager.ApplicationManager import io.eelo.appinstaller.common.ApplicationListAdapter import io.eelo.appinstaller.updates.viewModel.UpdatesViewModel Loading @@ -22,6 +23,7 @@ class UpdatesFragment : Fragment() { private lateinit var updatesViewModel: UpdatesViewModel private var applicationManager: ApplicationManager? = null private lateinit var recyclerView: RecyclerView private var applicationList = ArrayList<Application>() fun initialise(applicationManager: ApplicationManager) { this.applicationManager = applicationManager Loading @@ -36,25 +38,42 @@ class UpdatesFragment : Fragment() { updatesViewModel = ViewModelProviders.of(activity!!).get(UpdatesViewModel::class.java) recyclerView = view.findViewById(R.id.app_list) val splashContainer = view.findViewById<LinearLayout>(R.id.splash_container) val progressBar = view.findViewById<ProgressBar>(R.id.progress_bar) val errorContainer = view.findViewById<LinearLayout>(R.id.error_container) val errorDescription = view.findViewById<TextView>(R.id.error_description) // Initialise UI elements updatesViewModel.initialise(applicationManager!!) initializeRecyclerView() recyclerView.visibility = View.GONE progressBar.visibility = View.VISIBLE errorContainer.visibility = View.GONE splashContainer.visibility = View.GONE view.findViewById<TextView>(R.id.error_resolve).setOnClickListener { progressBar.visibility = View.VISIBLE updatesViewModel.loadApplicationList(context!!) } // Bind recycler view adapter to search results list in view model // Initialise recycler view recyclerView.setHasFixedSize(true) recyclerView.layoutManager = LinearLayoutManager(context) recyclerView.adapter = ApplicationListAdapter(activity!!, applicationList) // Bind recycler view adapter to outdated applications list in view model updatesViewModel.getApplications().observe(this, Observer { if (it!!.isNotEmpty()) { recyclerView.adapter.notifyDataSetChanged() if (it != null) { applicationList.clear() applicationList.addAll(it) progressBar.visibility = View.GONE recyclerView.adapter.notifyDataSetChanged() recyclerView.scrollToPosition(0) if (applicationList.isEmpty()) { recyclerView.visibility = View.GONE splashContainer.visibility = View.VISIBLE } else { splashContainer.visibility = View.GONE recyclerView.visibility = View.VISIBLE } } }) Loading @@ -64,6 +83,8 @@ class UpdatesFragment : Fragment() { errorDescription.text = activity!!.getString(Common.getScreenErrorDescriptionId(it)) errorContainer.visibility = View.VISIBLE progressBar.visibility = View.GONE splashContainer.visibility = View.GONE recyclerView.visibility = View.GONE } else { errorContainer.visibility = View.GONE } Loading @@ -74,25 +95,23 @@ class UpdatesFragment : Fragment() { return view } private fun initializeRecyclerView() { recyclerView.setHasFixedSize(true) recyclerView.layoutManager = LinearLayoutManager(context) recyclerView.adapter = ApplicationListAdapter(activity!!, updatesViewModel.getApplications().value!!) } override fun onResume() { super.onResume() if (::updatesViewModel.isInitialized) { updatesViewModel.getApplications().value!!.forEach { application -> updatesViewModel.getApplications().value?.let { it.forEach { application -> application.checkForStateUpdate(context!!) } } } } fun decrementApplicationUses() { if (::updatesViewModel.isInitialized) { updatesViewModel.getApplications().value!!.forEach { it.decrementUses() updatesViewModel.getApplications().value?.let { it.forEach { application -> application.decrementUses() } } } } Loading
app/src/main/java/io/eelo/appinstaller/updates/model/OutdatedApplicationsFileReader.kt 0 → 100644 +44 −0 Original line number Diff line number Diff line package io.eelo.appinstaller.updates.model import android.content.Context import android.os.AsyncTask import io.eelo.appinstaller.application.model.Application import io.eelo.appinstaller.application.model.State import io.eelo.appinstaller.applicationmanager.ApplicationManager import io.eelo.appinstaller.utils.Constants import java.io.BufferedReader import java.io.InputStreamReader import java.lang.Exception class OutdatedApplicationsFileReader(private val applicationManager: ApplicationManager, private val callback: UpdatesModelInterface) : AsyncTask<Context, Void, ArrayList<Application>>() { override fun doInBackground(vararg context: Context): ArrayList<Application> { val applications = ArrayList<Application>() try { context[0].openFileInput(Constants.OUTDATED_APPLICATIONS_FILENAME).use { val inputStreamReader = InputStreamReader(it) val bufferedReader = BufferedReader(inputStreamReader) bufferedReader.forEachLine { packageName -> val application = applicationManager.findOrCreateApp(packageName) val error = application.assertBasicData(context[0]) if (error == null) { if (application.state == State.NOT_UPDATED) { applications.add(application) } } } bufferedReader.close() inputStreamReader.close() it.close() } } catch (exception: Exception) { exception.printStackTrace() } return applications } override fun onPostExecute(result: ArrayList<Application>) { callback.onAppsFound(result) } }