Commit 19b21cd7 authored by jo's avatar jo
Browse files

big_changes

parent 825fae3b
package io.eelo.appinstaller.api
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import io.eelo.appinstaller.application.model.data.FullData
import io.eelo.appinstaller.utils.Constants
import java.net.URL
class AppDetailRequest(private val id: String) {
companion object {
private val reader = ObjectMapper().readerFor(Result::class.java)
}
fun request(): FullData {
return reader.readValue<Result>(URL(Constants.BASE_URL + "apps?action=app_detail&id=$id")).app
}
class Result @JsonCreator
constructor(@JsonProperty("app") val app: FullData,
@JsonProperty("success") private val success: Boolean)
}
\ No newline at end of file
package io.eelo.appinstaller.api
import android.content.Context
import com.fasterxml.jackson.annotation.JsonAnySetter
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import io.eelo.appinstaller.application.model.Application
import io.eelo.appinstaller.application.model.InstallManager
import io.eelo.appinstaller.application.model.data.FullData
import io.eelo.appinstaller.utils.ApplicationParser
import io.eelo.appinstaller.utils.Constants
import java.net.URL
class HomeRequest {
companion object {
private val reader = ObjectMapper().readerFor(HomeResult::class.java)
}
fun request(): HomeResult {
return reader.readValue(URL(Constants.BASE_URL + "apps?action=list_home"))
}
class HomeResult @JsonCreator
constructor(@JsonProperty("success") private val success: Boolean,
@JsonProperty("home") private val home: SubHomeResult) {
fun getBannerApps(installManager: InstallManager, context: Context): ArrayList<Application> {
return ApplicationParser.parseToApps(installManager, context, home.bannerApps)
}
fun getApps(installManager: InstallManager, context: Context): HashMap<String, ArrayList<Application>> {
val apps = HashMap<String, ArrayList<Application>>()
home.apps.forEach { category, appsData ->
apps[category] = ApplicationParser.parseToApps(installManager, context, appsData.toTypedArray())
}
return apps
}
}
class SubHomeResult @JsonCreator
constructor(@JsonProperty("banner_apps") val bannerApps: Array<FullData>) {
val apps = HashMap<String, ArrayList<FullData>>()
@JsonAnySetter
fun append(key: String, value: Any) {
val apps = value as ArrayList<*>
val appsData = ArrayList<FullData>()
apps.forEach {
val data = it as LinkedHashMap<*, *>
val appData = FullData(
data["package_name"] as String,
data["_id"] as String,
data["name"] as String,
data["last_modified"] as String,
data["latest_version"] as String,
data["author"] as String,
data["icon_image_path"] as String,
(data["other_images_path"] as List<String>).toTypedArray(),
data["category"] as String,
data["created_on"] as String,
data["source"] as String,
data["description"] as String,
data["app_link"] as String,
data["licence"] as String)
for (pair in data) {
appData.jsonCreator(pair.key as String, pair.value)
}
appsData.add(appData)
}
this.apps[key] = appsData
}
}
}
\ No newline at end of file
package io.eelo.appinstaller.categories.category.model
package io.eelo.appinstaller.api
import android.content.Context
import android.os.AsyncTask
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import io.eelo.appinstaller.application.model.Application
import io.eelo.appinstaller.application.model.ApplicationData
import io.eelo.appinstaller.application.model.InstallManager
import io.eelo.appinstaller.application.model.data.FullData
import io.eelo.appinstaller.utils.ApplicationParser
import io.eelo.appinstaller.utils.Constants
import java.net.URL
class Loader(private val page: Int, private val categoryModel: CategoryModel) : AsyncTask<Context, Any, ArrayList<Application>>() {
class ListApplicationsRequest(private val category: String, private val page: Int, private val resultsPerPage: Int) {
companion object {
private val jsonReader = ObjectMapper().readerFor(CategoryApplicationsResult::class.java)
private val reader = ObjectMapper().readerFor(ListApplicationsResult::class.java)
}
override fun doInBackground(vararg params: Context): ArrayList<Application> {
val context = params[0]
val result = jsonReader.readValue<CategoryApplicationsResult>(URL(Constants.BASE_URL + "apps?action=list_apps&category=" + categoryModel.category + "&nres=" + Constants.RESULTS_PER_PAGE + "&page=" + page))
return ApplicationParser.parseToApps(categoryModel.installManager, context, result.apps)
fun request(): ListApplicationsResult {
return reader.readValue(URL(Constants.BASE_URL + "apps?action=list_apps&category=$category&nres=$resultsPerPage&page=$page"))
}
override fun onPostExecute(result: ArrayList<Application>) {
categoryModel.categoryApplicationsList.value = result
class ListApplicationsResult @JsonCreator
constructor(@JsonProperty("pages") val pages: Int,
@JsonProperty("apps") private val apps: Array<FullData>) {
fun getApplications(installManager: InstallManager, context: Context): ArrayList<Application> {
return ApplicationParser.parseToApps(installManager, context, apps)
}
}
class CategoryApplicationsResult @JsonCreator
constructor(@JsonProperty("pages") val pages: Int,
@JsonProperty("apps") val apps: Array<ApplicationData>)
}
}
\ No newline at end of file
package io.eelo.appinstaller.categories.model
package io.eelo.appinstaller.api
import android.os.AsyncTask
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import io.eelo.appinstaller.utils.Constants
import java.net.URL
class Loader(private val categoriesModel: CategoriesModel) : AsyncTask<Any, Any, Loader.ListCategoriesResult>() {
class ListCategoriesRequest {
companion object {
private val jsonReader = ObjectMapper().readerFor(ListCategoriesResult::class.java)
private val reader = ObjectMapper().readerFor(ListCategoriesResult::class.java)
}
override fun doInBackground(vararg params: Any): ListCategoriesResult {
return jsonReader.readValue<ListCategoriesResult>(URL(Constants.BASE_URL + "apps?action=list_cat"))
}
override fun onPostExecute(result: ListCategoriesResult) {
val applicationsCategoriesList = ArrayList<Category>()
val gamesCategoriesList = ArrayList<Category>()
result.appsCategories.forEach { id ->
applicationsCategoriesList.add(Category(null, id))
}
result.gamesCategories.forEach { id ->
gamesCategoriesList.add(Category(null, id))
}
categoriesModel.applicationsCategoriesList.value = applicationsCategoriesList
categoriesModel.gamesCategoriesList.value = gamesCategoriesList
fun request(): ListCategoriesResult {
return reader.readValue<ListCategoriesResult>(URL(Constants.BASE_URL + "apps?action=list_cat"))
}
class ListCategoriesResult @JsonCreator
constructor(@JsonProperty("apps") val appsCategories: Array<String>,
@JsonProperty("games") val gamesCategories: Array<String>)
}
}
\ No newline at end of file
package io.eelo.appinstaller.application.model
package io.eelo.appinstaller.api
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import io.eelo.appinstaller.application.model.data.FullData
import io.eelo.appinstaller.utils.Constants
import java.net.URL
class PackageNameFinder @JsonCreator
constructor(@JsonProperty("pages") val pages: Int,
@JsonProperty("numberOfResults") val numberOfResults: Int,
@JsonProperty("apps") val apps: Array<ApplicationData>) {
class PackageNameSearchRequest(private val packageName: String) {
companion object {
private val reader = ObjectMapper().readerFor(PackageNameFinder::class.java)
private val reader = ObjectMapper().readerFor(SearchResult::class.java)
}
fun request(): SearchResult {
return reader.readValue(URL(Constants.BASE_URL + "apps?action=search&keyword=$packageName&by=package_name"))
}
fun find(packageName: String): ApplicationData? {
val url = URL(Constants.BASE_URL + "apps?action=search&by=package_name&keyword=$packageName")
val result = reader.readValue<PackageNameFinder>(url.openStream())
result.apps.forEach {
println(url)
class SearchResult @JsonCreator
constructor(@param:JsonProperty("pages") val pages: Int,
@param:JsonProperty("numberOfResults") val resultsNumber: Int,
@param:JsonProperty("apps") val appResults: Array<FullData>) {
fun findOneAppData(packageName: String): FullData? {
appResults.forEach {
if (it.packageName == packageName) {
return it
}
......@@ -26,5 +31,4 @@ constructor(@JsonProperty("pages") val pages: Int,
return null
}
}
}
\ No newline at end of file
package io.eelo.appinstaller.api
import android.content.Context
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import io.eelo.appinstaller.application.model.Application
import io.eelo.appinstaller.application.model.InstallManager
import io.eelo.appinstaller.application.model.data.BasicData
import io.eelo.appinstaller.utils.ApplicationParser
import io.eelo.appinstaller.utils.Constants
import java.net.URL
class SearchRequest(private val keyword: String, private val page: Int, private val resultsPerPage: Int) {
companion object {
private val reader = ObjectMapper().readerFor(SearchResult::class.java)
}
fun request(): SearchResult {
return reader.readValue(URL(Constants.BASE_URL + "apps?action=search&keyword=$keyword&page=$page&nres=$resultsPerPage"))
}
class SearchResult @JsonCreator
constructor(@param:JsonProperty("pages") val pages: Int,
@param:JsonProperty("numberOfResults") val resultsNumber: Int,
@param:JsonProperty("apps") val appResults: Array<BasicData>) {
fun getApplications(installManager: InstallManager, context: Context): List<Application> {
return ApplicationParser.parseToApps(installManager, context, appResults)
}
}
}
\ No newline at end of file
......@@ -3,7 +3,6 @@ package io.eelo.appinstaller.application
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.PackageManager
import android.os.AsyncTask
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
......@@ -34,11 +33,9 @@ class ApplicationActivity : AppCompatActivity(), ApplicationStateListener {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowTitleEnabled(false)
// Get application package name from intent
val applicationPackageName: String? = intent.getStringExtra(APPLICATION_PACKAGE_NAME_KEY)
if (!applicationPackageName.isNullOrEmpty()) {
// Bind to the InstallManagerService and initialise applicationF
InitialiseTask().executeOnExecutor(Common.EXECUTOR, applicationPackageName)
initialise(applicationPackageName!!)
}
}
......@@ -62,22 +59,26 @@ class ApplicationActivity : AppCompatActivity(), ApplicationStateListener {
return true
}
@SuppressLint("SetTextI18n")
private fun onApplicationInfoLoaded() {
val basicData = application.basicData!!
val fullData = application.fullData!!
application.loadIcon(app_icon)
app_title.text = application.data.name
app_author.text = application.data.author
app_category.text = Common.getCategoryTitle(application.data.category)
app_description.text = Html.fromHtml(application.data.description)
app_title.text = basicData.name
app_author.text = basicData.author
app_category.text = Common.getCategoryTitle(fullData.category)
app_description.text = Html.fromHtml(fullData.description)
app_description_container.setOnClickListener {
val intent = Intent(this, ApplicationDescriptionActivity::class.java)
intent.putExtra(APPLICATION_DESCRIPTION_KEY, application.data.description)
intent.putExtra(APPLICATION_DESCRIPTION_KEY, application.fullData!!.description)
startActivity(intent)
}
app_rating.text = application.data.stars.toString() + "/10"
app_privacy_score.text = application.data.privacyScore.toString() + "/10"
app_energy_score.text = application.data.energyScore.toString() + "/10"
app_rating.text = basicData.score.toString() + "/10"
app_privacy_score.text = fullData.privacyScore.toString() + "/10"
app_energy_score.text = fullData.energyScore.toString() + "/10"
app_install.setOnClickListener {
application.buttonClicked(this, this)
application.buttonClicked(this)
}
application.addListener(this)
stateChanged(application.state)
......@@ -86,7 +87,7 @@ class ApplicationActivity : AppCompatActivity(), ApplicationStateListener {
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
if (requestCode == Constants.STORAGE_PERMISSION_REQUEST_CODE) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
application.buttonClicked(this, this)
application.buttonClicked(this)
} else if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_DENIED) {
Toast.makeText(this, resources.getString(R.string.error_storage_permission_denied), Toast.LENGTH_LONG).show()
}
......@@ -111,20 +112,14 @@ class ApplicationActivity : AppCompatActivity(), ApplicationStateListener {
// TODO alert the user of the error (while downloading)
}
private inner class InitialiseTask : AsyncTask<String, Any, Any>() {
override fun doInBackground(vararg params: String): Any? {
val context = this@ApplicationActivity
val installManager = installManagerGetter.connectAndGet(context)
application = installManager.findOrCreateApp(context, ApplicationData(params[0]))
if (application.data.fullnessLevel != 2) {
application.searchFullData(context)
}
return null
}
override fun onPostExecute(result: Any?) {
private fun initialise(packageName: String) {
Execute({
val installManager = installManagerGetter.connectAndGet(this)
application = installManager.findOrCreateApp(packageName)
application.assertFullData(this)
}, {
onApplicationInfoLoaded()
}
})
}
override fun onDestroy() {
......
......@@ -38,7 +38,7 @@ class ApplicationViewHolder(private val activity: Activity, private val view: Vi
}
}
installButton.setOnClickListener {
application?.buttonClicked(view.context, activity)
application?.buttonClicked(activity)
}
}
......@@ -48,14 +48,18 @@ class ApplicationViewHolder(private val activity: Activity, private val view: Vi
this.application?.removeListener(this)
this.application = app
app.addListener(this)
title.text = app.data.name
author.text = app.data.author
ratingBar.rating = app.data.stars
title.text = app.basicData!!.name
author.text = app.basicData!!.author
ratingBar.rating = app.basicData!!.score
val decimalFormat = DecimalFormat("##.0")
rating.text = decimalFormat.format(app.data.stars).toString()
rating.setTextColor(findStarsColor(app.data.stars))
privacyScore.text = app.data.privacyScore.toString()
privacyScore.setTextColor(findPrivacyColor(app.data.privacyScore))
rating.text = decimalFormat.format(app.basicData!!.score).toString()
rating.setTextColor(findStarsColor(app.basicData!!.score))
Execute({
app.assertFullData(view.context)
}, {
privacyScore.text = app.fullData!!.privacyScore.toString()
privacyScore.setTextColor(findPrivacyColor(app.fullData!!.privacyScore))
})
stateChanged(app.state)
}
......
package io.eelo.appinstaller.application
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.AsyncTask
import io.eelo.appinstaller.utils.Constants
import java.io.IOException
import java.net.URL
class ImageDownloader(private val listener: (Bitmap) -> Unit) : AsyncTask<String, Void, Bitmap>() {
override fun doInBackground(vararg image: String): Bitmap? {
try {
val url = URL(Constants.BASE_URL + "media/" + image[0])
return BitmapFactory.decodeStream(url.openStream())
} catch (ignored: IOException) {
}
return null
}
override fun onPostExecute(bitmap: Bitmap?) {
if (bitmap != null) {
listener.invoke(bitmap)
}
}
}
......@@ -32,7 +32,7 @@ class SmallApplicationViewHolder(private val activity: Activity, private val vie
}
}
installButton.setOnClickListener {
application?.buttonClicked(view.context, activity)
application?.buttonClicked(activity)
}
}
......@@ -42,7 +42,7 @@ class SmallApplicationViewHolder(private val activity: Activity, private val vie
this.application?.removeListener(this)
this.application = app
app.addListener(this)
title.text = app.data.name
title.text = app.basicData!!.name
stateChanged(app.state)
}
......
......@@ -4,26 +4,24 @@ import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.widget.ImageView
import io.eelo.appinstaller.api.AppDetailRequest
import io.eelo.appinstaller.api.PackageNameSearchRequest
import io.eelo.appinstaller.application.model.State.*
import io.eelo.appinstaller.application.model.data.BasicData
import io.eelo.appinstaller.application.model.data.FullData
import io.eelo.appinstaller.utils.Constants
import io.eelo.appinstaller.utils.Execute
import java.io.IOException
import java.util.concurrent.atomic.AtomicInteger
class Application(val data: ApplicationData, context: Context, private val installManager: InstallManager) {
class Application(val packageName: String, private val installManager: InstallManager) {
private val uses = AtomicInteger(0)
private val info = ApplicationInfo(data)
private val info = ApplicationInfo(packageName)
private val stateManager = StateManager(info, this)
init {
// TODO must change these lines, when API give the application's version
// if (data.assertFullData()) {
// stateManager.find(context)
// }
}
var basicData: BasicData? = null
var fullData: FullData? = null
fun addListener(listener: ApplicationStateListener) {
stateManager.addListener(listener)
......@@ -47,30 +45,28 @@ class Application(val data: ApplicationData, context: Context, private val insta
}
@Synchronized
fun buttonClicked(context: Context, activity: Activity?) {
fun buttonClicked(activity: Activity) {
when (stateManager.state) {
INSTALLED -> info.launch(context)
INSTALLED -> info.launch(activity)
DOWNLOADED -> {
stateManager.changeState(INSTALLING)
installManager.install(data.packageName)
prepareInstall()
}
NOT_UPDATED, NOT_DOWNLOADED -> {
if (canWriteStorage(activity)) {
stateManager.changeState(DOWNLOADING)
installManager.download(data.packageName)
installManager.download(packageName)
}
}
DOWNLOADING -> {
}
INSTALLING -> {
}
}
}
private fun canWriteStorage(activity: Activity?): Boolean {
private fun canWriteStorage(activity: Activity): Boolean {
return if (android.os.Build.VERSION.SDK_INT >= 23) {
if (activity!!.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), Constants.STORAGE_PERMISSION_REQUEST_CODE)
false
} else {
......@@ -82,44 +78,92 @@ class Application(val data: ApplicationData, context: Context, private val insta
}
fun download(context: Context) {
searchFullData(context)
downloader = info.createDownloader()
assertFullData(context)
downloader = Downloader()
stateManager.notifyDownloading(downloader!!)
try {
downloader!!.download()
stateManager.changeState(INSTALLING)
installManager.install(data.packageName)
stateManager.find(context)
downloader!!.download(fullData!!, info.getApkFile(basicData!!))
downloader = null
prepareInstall()
} catch (e: IOException) {
e.printStackTrace()
stateManager.find(context)
stateManager.find(context, basicData!!)
stateManager.notifyError()
}
}
private fun prepareInstall() {
stateManager.changeState(INSTALLING)
installManager.install(packageName)
}
fun install(context: Context) {
info.install(context)
stateManager.find(context)
info.install(context, basicData!!)
stateManager.find(context, basicData!!)
}
fun isUsed(): Boolean {
return uses.get() !=