Skip to content

Commit

Permalink
Initial Updater Page and workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
sounddrill31 committed Aug 19, 2024
1 parent c0a2826 commit 392e260
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 19 deletions.
28 changes: 11 additions & 17 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ jobs:
git config --global user.name "sounddrill31"
git config --global user.email "sounddrill31@gmail.com"
id: pwd
- name: Versioning
run: |
if [ -z "${{ github.run_id }}" ]; then
echo "Run ID is blank!";
else
RUN_ID="${github.run_id}"
sed -i '/^import/a\private val buildRunId = "'"$RUN_ID"'"' app/src/main/java/com/zeusinstitute/upiapp/Update.kt
fi


- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
Expand Down Expand Up @@ -64,20 +74,4 @@ jobs:
tag_name: ${{ github.run_id }} ${{ github.pull_request_target }}
draft: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Re-Configure Git
run: |
git config user.name github-actions
git config user.email github-actions@github.com
- name: Update gh-pages branch
run: |
git fetch
git reset --hard
git switch gh-pages
mkdir -p redirects/app-updates
echo "<meta http-equiv=\"refresh\" content=\"0; url=https://github.com/ZeusInstitute-OSS/UPI-Viewer/releases/download/${{ github.run_id }}/app-debug-signed.apk\"/>" > redirects/app-updates/index.html
git add redirects/app-updates/index.html
git commit -m "Update app update redirect to version ${{ github.run_id }}"
git push origin gh-pages
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 4 additions & 0 deletions app/src/main/java/com/zeusinstitute/upiapp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ class MainActivity : AppCompatActivity() {
findNavController(R.id.nav_host_fragment_content_main).navigate(R.id.action_firstFragment_to_dynamicFragment)
true
}
R.id.Update -> {
findNavController(R.id.nav_host_fragment_content_main).navigate(R.id.action_firstFragment_to_Update)
true
}
android.R.id.home -> {
findNavController(R.id.nav_host_fragment_content_main).navigateUp()
return true
Expand Down
162 changes: 162 additions & 0 deletions app/src/main/java/com/zeusinstitute/upiapp/Update.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package com.zeusinstitute.upiapp

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONArray
import java.net.HttpURLConnection
import java.net.URL
private val buildRunId: Long = 10448859905

class UpdateFragment : Fragment() {
private val TAG = "UpdateFragment"
private val releasesUrl = "https://api.github.com/repos/ZeusInstitute-OSS/UPI-Viewer/releases"

private lateinit var checkUpdateButton: Button
private lateinit var noUpdateText: TextView
private lateinit var downloadProgressBar: ProgressBar

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_update, container, false) // Use your fragment layout

checkUpdateButton = view.findViewById(R.id.checkUpdateButton)
noUpdateText = view.findViewById(R.id.noUpdateText)
downloadProgressBar = view.findViewById(R.id.downloadProgressBar)


checkUpdateButton.setOnClickListener {
if (buildRunId == 0L) {
Toast.makeText(context, "Updating is disabled", Toast.LENGTH_SHORT).show()
} else {
lifecycleScope.launch {
checkForUpdate()
}
}
}



return view
}

private suspend fun checkForUpdate() {
withContext(Dispatchers.Main) {
checkUpdateButton.isEnabled = false
noUpdateText.visibility = View.GONE
downloadProgressBar.visibility = View.GONE
}

val latestRelease = getLatestRelease()

if (latestRelease != null && latestRelease.runId > buildRunId) {
downloadApk(latestRelease.apkUrl)
} else {
withContext(Dispatchers.Main) {
noUpdateText.text = "No updates available"
noUpdateText.visibility = View.VISIBLE
checkUpdateButton.isEnabled = true
}
}
}

private suspend fun getLatestRelease(): Release? {
return withContext(Dispatchers.IO) {
try {
val connection = URL(releasesUrl).openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.setRequestProperty("Accept", "application/vnd.github+json") // Specify GitHub API version

val responseCode = connection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
val response = connection.inputStream.bufferedReader().use { it.readText() }
val jsonArray = JSONArray(response)

if (jsonArray.length() > 0) {
val latestRelease = jsonArray.getJSONObject(0)
val runId = latestRelease.getLong("id")
val tagName = latestRelease.getString("tag_name") // Get tag name for APK URL
val apkUrl = "https://github.com/ZeusInstitute-OSS/UPI-Viewer/releases/download/$tagName/app-debug-signed.apk"
Release(runId, apkUrl)
} else {
null
}
} else {
Log.e(TAG, "Error getting latest release: HTTP $responseCode")
null
}
} catch (e: Exception) {
Log.e(TAG, "Error getting latest release", e)
null
}
}
}
private suspend fun downloadApk(url: String) {
withContext(Dispatchers.Main) {
downloadProgressBar.visibility = View.VISIBLE
downloadProgressBar.progress = 0
}

withContext(Dispatchers.IO) {
try {
val connection = URL(url).openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.connectTimeout = 15000
connection.readTimeout = 15000

if (connection.responseCode == HttpURLConnection.HTTP_OK) {
val contentLength = connection.contentLength
var bytesRead = 0
val buffer = ByteArray(8192)
var bytes: Int

connection.inputStream.use { input ->
while (input.read(buffer).also { bytes = it } >= 0) {
bytesRead += bytes
val progress = (bytesRead.toFloat() / contentLength * 100).toInt()
withContext(Dispatchers.Main) {
downloadProgressBar.progress = progress
}
}
}

// Here you would save the APK and initiate the installation
android.util.Log.i(TAG, "APK downloaded successfully")
} else {
android.util.Log.e(TAG, "HTTP error: ${connection.responseCode}")
withContext(Dispatchers.Main) {
noUpdateText.text = "Update failed: HTTP ${connection.responseCode}"
noUpdateText.visibility = View.VISIBLE
}
}
} catch (e: Exception) {
android.util.Log.e(TAG, "Error downloading APK", e)
withContext(Dispatchers.Main) {
noUpdateText.text = "Update failed: ${e.message}"
noUpdateText.visibility = View.VISIBLE
}
}
}

withContext(Dispatchers.Main) {
downloadProgressBar.visibility = View.GONE
checkUpdateButton.isEnabled = true
}
}

data class Release(val runId: Long, val apkUrl: String)
}
40 changes: 40 additions & 0 deletions app/src/main/res/layout/fragment_update.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">

<Button
android:id="@+id/checkUpdateButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Check for Updates"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<TextView
android:id="@+id/noUpdateText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No updates found"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/checkUpdateButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp" />

<ProgressBar
android:id="@+id/downloadProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/checkUpdateButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp" />

</androidx.constraintlayout.widget.ConstraintLayout>
5 changes: 3 additions & 2 deletions app/src/main/res/menu/menu_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<item
android:id="@+id/SplitBill"
android:title="Split The Bill" />

</menu>
</item>
<item android:title="Hardware" ></item>
Expand All @@ -29,7 +28,9 @@
<item
android:id="@+id/log_in"
android:title="@string/login"/>
<item android:title="Update" />
<item
android:id="@+id/Update"
android:title="Check Updates" />
<item
android:enabled="true"
android:id="@+id/AboutApp"
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/navigation/nav_graph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<action
android:id="@+id/action_firstFragment_to_splitBillFragment"
app:destination="@id/splitBillFragment" />
<action
android:id="@+id/action_firstFragment_to_Update"
app:destination="@id/Update" />
</fragment>
<fragment
android:id="@+id/login"
Expand All @@ -44,4 +47,8 @@
android:id="@+id/splitBillFragment"
android:name="SplitBillFragment"
android:label="Split the Bill" />
<fragment
android:id="@+id/Update"
android:name="com.zeusinstitute.upiapp.UpdateFragment"
android:label="Update"/>
</navigation>

0 comments on commit 392e260

Please sign in to comment.