diff --git a/app/src/main/java/com/finnmglas/launcher/ChooseActivity.kt b/app/src/main/java/com/finnmglas/launcher/ChooseActivity.kt index 7037d03..7c91398 100644 --- a/app/src/main/java/com/finnmglas/launcher/ChooseActivity.kt +++ b/app/src/main/java/com/finnmglas/launcher/ChooseActivity.kt @@ -2,22 +2,20 @@ package com.finnmglas.launcher import android.app.Activity import android.content.Intent -import android.graphics.Color -import android.net.Uri import android.os.Bundle import android.view.View import android.view.WindowManager -import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.finnmglas.launcher.choose.AppsRecyclerAdapter import com.finnmglas.launcher.extern.* import kotlinx.android.synthetic.main.activity_choose.* class ChooseActivity : AppCompatActivity() { - /** Activity Lifecycle functions */ - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -42,54 +40,25 @@ class ChooseActivity : AppCompatActivity() { // As older APIs somehow do not recognize the xml defined onClick activity_choose_close.setOnClickListener() { finish() } + // get info about which action this activity is open for val bundle = intent.extras val action = bundle!!.getString("action") // why choose an app val forApp = bundle.getString("forApp") // which app we choose - if (action == "launch") - activity_choose_heading.text = getString(R.string.choose_title_launch) - else if (action == "pick") - activity_choose_heading.text = getString(R.string.choose_title) - else if (action == "uninstall") - activity_choose_heading.text = getString(R.string.choose_title_remove) + when (action) { + "view" -> activity_choose_heading.text = getString(R.string.choose_title_view) + "pick" -> activity_choose_heading.text = getString(R.string.choose_title) + } - /* Build Layout */ + // set up the list / recycler + viewManager = LinearLayoutManager(this) + viewAdapter = AppsRecyclerAdapter( this, action, forApp) - for (resolveInfo in appsList) { - val app = resolveInfo.activityInfo - - // creating TextView programmatically - val tvdynamic = TextView(this) - tvdynamic.textSize = 24f - tvdynamic.text = app.loadLabel(packageManager).toString() - tvdynamic.setTextColor(Color.parseColor("#cccccc")) - - if (action == "launch"){ - tvdynamic.setOnClickListener { startActivity(packageManager.getLaunchIntentForPackage(app.packageName)) } - } - else if (action == "pick"){ - tvdynamic.setOnClickListener { - val returnIntent = Intent() - returnIntent.putExtra("value", app.packageName) - returnIntent.putExtra("forApp", forApp) - setResult( - REQUEST_CHOOSE_APP, - returnIntent - ) - finish() - } - } - else if (action == "uninstall"){ - tvdynamic.setOnClickListener { - val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE) - intent.data = Uri.parse("package:" + app.packageName) - intent.putExtra(Intent.EXTRA_RETURN_RESULT, true) - startActivityForResult(intent, - REQUEST_UNINSTALL - ) - } - } - activity_choose_apps_list.addView(tvdynamic) + activity_choose_apps_recycler_view.apply { + // improve performance (since content changes don't change the layout size) + setHasFixedSize(true) + layoutManager = viewManager + adapter = viewAdapter } } @@ -98,7 +67,6 @@ class ChooseActivity : AppCompatActivity() { if (requestCode == REQUEST_UNINSTALL) { if (resultCode == Activity.RESULT_OK) { Toast.makeText(this, getString(R.string.choose_removed_toast), Toast.LENGTH_LONG).show() - updateAppList(packageManager) finish() } else if (resultCode == Activity.RESULT_FIRST_USER) { Toast.makeText(this, getString(R.string.choose_not_removed_toast), Toast.LENGTH_LONG).show() diff --git a/app/src/main/java/com/finnmglas/launcher/MainActivity.kt b/app/src/main/java/com/finnmglas/launcher/MainActivity.kt index d16cfa5..8934ccd 100644 --- a/app/src/main/java/com/finnmglas/launcher/MainActivity.kt +++ b/app/src/main/java/com/finnmglas/launcher/MainActivity.kt @@ -10,6 +10,8 @@ import android.util.DisplayMetrics import android.view.* import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GestureDetectorCompat +import androidx.recyclerview.widget.RecyclerView +import com.finnmglas.launcher.choose.AppsRecyclerAdapter import com.finnmglas.launcher.extern.* import kotlinx.android.synthetic.main.activity_main.* import java.text.SimpleDateFormat @@ -17,6 +19,9 @@ import java.util.* import kotlin.concurrent.fixedRateTimer import kotlin.math.abs +// used for the apps drawer / menu (ChooseActivity) +lateinit var viewAdapter: RecyclerView.Adapter<*> +lateinit var viewManager: RecyclerView.LayoutManager class MainActivity : AppCompatActivity(), GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener { @@ -32,7 +37,6 @@ class MainActivity : AppCompatActivity(), // timers private var clockTimer = Timer() private var tooltipTimer = Timer() - private var loadAppsTimer = Timer() private var settingsIconShown = false @@ -77,6 +81,9 @@ class MainActivity : AppCompatActivity(), // As older APIs somehow do not recognize the xml defined onClick activity_main_settings_icon.setOnClickListener() { openSettings() } + // Load apps list first - speed up settings that way + AsyncTask.execute { viewAdapter = AppsRecyclerAdapter( this, "", "") } + // First Startup if (!sharedPref.getBoolean("startedBefore", false)){ startActivity(Intent(this, FirstStartupActivity::class.java)) @@ -125,18 +132,11 @@ class MainActivity : AppCompatActivity(), activity_main_date_view.text = d } } - - val pm = packageManager - - loadAppsTimer = fixedRateTimer("loadAppsTimer", true, 0L, 30000) { - AsyncTask.execute { updateAppList(pm) } - } } override fun onPause() { super.onPause() clockTimer.cancel() - loadAppsTimer.cancel() } private fun openSettings(){ diff --git a/app/src/main/java/com/finnmglas/launcher/choose/AppInfo.kt b/app/src/main/java/com/finnmglas/launcher/choose/AppInfo.kt new file mode 100644 index 0000000..4221dad --- /dev/null +++ b/app/src/main/java/com/finnmglas/launcher/choose/AppInfo.kt @@ -0,0 +1,10 @@ +package com.finnmglas.launcher.choose + +import android.graphics.drawable.Drawable + +class AppInfo { + var label: CharSequence? = null + var packageName: CharSequence? = null + var icon: Drawable? = null + var isSystemApp: Boolean = false +} \ No newline at end of file diff --git a/app/src/main/java/com/finnmglas/launcher/choose/AppsRecyclerAdapter.kt b/app/src/main/java/com/finnmglas/launcher/choose/AppsRecyclerAdapter.kt new file mode 100644 index 0000000..0fcbb26 --- /dev/null +++ b/app/src/main/java/com/finnmglas/launcher/choose/AppsRecyclerAdapter.kt @@ -0,0 +1,97 @@ +package com.finnmglas.launcher.choose + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.net.Uri +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.finnmglas.launcher.R +import com.finnmglas.launcher.extern.FontAwesome +import com.finnmglas.launcher.extern.REQUEST_CHOOSE_APP +import com.finnmglas.launcher.extern.REQUEST_UNINSTALL + + +class AppsRecyclerAdapter(val activity: Activity, val action: String?, val forApp: String?): + RecyclerView.Adapter() { + + private val appsList: MutableList + + inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), + View.OnClickListener { + var textView: TextView = itemView.findViewById(R.id.choose_row_app_name) + var img: ImageView = itemView.findViewById(R.id.choose_row_app_icon) as ImageView + var delete: FontAwesome = itemView.findViewById(R.id.choose_row_app_delete) + + override fun onClick(v: View) { + val pos = adapterPosition + val context: Context = v.context + val appPackageName = appsList[pos].packageName.toString() + + when (action){ + "view" -> { + val launchIntent: Intent = context.packageManager + .getLaunchIntentForPackage(appPackageName)!! + context.startActivity(launchIntent) + } + "pick" -> { + val returnIntent = Intent() + returnIntent.putExtra("value", appPackageName) + returnIntent.putExtra("forApp", forApp) + activity.setResult(REQUEST_CHOOSE_APP, returnIntent) + activity.finish() + } + } + } + + init { itemView.setOnClickListener(this) } + } + + override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { + val appLabel = appsList[i].label.toString() + val appPackageName = appsList[i].packageName.toString() + val appIcon = appsList[i].icon + val isSystemApp = appsList[i].isSystemApp + + viewHolder.textView.text = appLabel + viewHolder.img.setImageDrawable(appIcon) + + viewHolder.delete.setOnClickListener{ + val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE) + intent.data = Uri.parse("package:$appPackageName") + intent.putExtra(Intent.EXTRA_RETURN_RESULT, true) + activity.startActivityForResult(intent, REQUEST_UNINSTALL) + } + + viewHolder.delete.visibility = if(isSystemApp || action == "pick") View.INVISIBLE else View.VISIBLE + } + + override fun getItemCount(): Int { return appsList.size } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val inflater = LayoutInflater.from(parent.context) + val view: View = inflater.inflate(R.layout.recycler_apps_row, parent, false) + return ViewHolder(view) + } + + init { + val pm: PackageManager = activity.packageManager + appsList = ArrayList() + val i = Intent(Intent.ACTION_MAIN, null) + i.addCategory(Intent.CATEGORY_LAUNCHER) + val allApps = pm.queryIntentActivities(i, 0) + for (ri in allApps) { + val app = AppInfo() + app.label = ri.loadLabel(pm) + app.packageName = ri.activityInfo.packageName + app.icon = ri.activityInfo.loadIcon(pm) + appsList.add(app) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/finnmglas/launcher/extern/Functions.kt b/app/src/main/java/com/finnmglas/launcher/extern/Functions.kt index c2c967a..5bc9245 100644 --- a/app/src/main/java/com/finnmglas/launcher/extern/Functions.kt +++ b/app/src/main/java/com/finnmglas/launcher/extern/Functions.kt @@ -7,7 +7,6 @@ import android.content.DialogInterface import android.content.Intent import android.content.SharedPreferences import android.content.pm.PackageManager -import android.content.pm.ResolveInfo import android.graphics.* import android.net.Uri import android.os.Build @@ -30,8 +29,6 @@ var volumeDownApp = "" var calendarApp = "" var clockApp = "" -var appsList : MutableList = mutableListOf() - var background : Bitmap? = null var dominantColor = 0 @@ -126,13 +123,6 @@ fun isInstalled(uri: String, context: Context): Boolean { return false } -fun updateAppList(pm : PackageManager) { - val intent = Intent(Intent.ACTION_MAIN) - .addCategory(Intent.CATEGORY_LAUNCHER) - appsList = pm.queryIntentActivities(intent, 0) - appsList.sortBy { it.activityInfo.loadLabel(pm).toString() } -} - private fun getIntent(packageName: String, context: Context): Intent? { val intent: Intent? = context.packageManager.getLaunchIntentForPackage(packageName) intent?.addCategory(Intent.CATEGORY_LAUNCHER) diff --git a/app/src/main/java/com/finnmglas/launcher/settings/SettingsFragmentApps.kt b/app/src/main/java/com/finnmglas/launcher/settings/SettingsFragmentApps.kt index 62189ad..93d2915 100644 --- a/app/src/main/java/com/finnmglas/launcher/settings/SettingsFragmentApps.kt +++ b/app/src/main/java/com/finnmglas/launcher/settings/SettingsFragmentApps.kt @@ -42,9 +42,8 @@ class SettingsFragmentApps : Fragment() { setButtonColor(fragment_settings_apps_choose_vol_up_btn, vibrantColor) setButtonColor(fragment_settings_apps_choose_vol_down_btn, vibrantColor) - setButtonColor(fragment_settings_apps_launch_btn, vibrantColor) + setButtonColor(fragment_settings_apps_btn, vibrantColor) setButtonColor(fragment_settings_apps_install_btn, vibrantColor) - setButtonColor(fragment_settings_apps_remove_btn, vibrantColor) } // Action - selecting buttons @@ -56,9 +55,9 @@ class SettingsFragmentApps : Fragment() { fragment_settings_apps_choose_vol_down_btn.setOnClickListener{ chooseApp("volumeDownApp")} // App management buttons - fragment_settings_apps_launch_btn.setOnClickListener{ + fragment_settings_apps_btn.setOnClickListener{ val intent = Intent(this.context, ChooseActivity::class.java) - intent.putExtra("action", "launch") + intent.putExtra("action", "view") startActivity(intent) } fragment_settings_apps_install_btn.setOnClickListener{ @@ -72,11 +71,6 @@ class SettingsFragmentApps : Fragment() { .show() } } - fragment_settings_apps_remove_btn.setOnClickListener{ - val intent = Intent(this.context, ChooseActivity::class.java) - intent.putExtra("action", "uninstall") - startActivity(intent) - } super.onStart() } diff --git a/app/src/main/res/layout/activity_choose.xml b/app/src/main/res/layout/activity_choose.xml index e15028a..911d0cd 100644 --- a/app/src/main/res/layout/activity_choose.xml +++ b/app/src/main/res/layout/activity_choose.xml @@ -58,25 +58,19 @@ - - - - + app:layout_constraintTop_toBottomOf="@id/activity_choose_app_bar" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings_apps.xml b/app/src/main/res/layout/fragment_settings_apps.xml index cf0ca53..a1c3718 100644 --- a/app/src/main/res/layout/fragment_settings_apps.xml +++ b/app/src/main/res/layout/fragment_settings_apps.xml @@ -160,10 +160,10 @@