diff --git a/.github/workflows/android-workflow.yaml b/.github/workflows/android-workflow.yaml index 1889a112..76c982f2 100644 --- a/.github/workflows/android-workflow.yaml +++ b/.github/workflows/android-workflow.yaml @@ -29,6 +29,14 @@ jobs: env: PLATFORM_REDIRECT_URI: ${{ secrets.PLATFORM_REDIRECT_URI }} run: echo PLATFORM_REDIRECT_URI=\"$PLATFORM_REDIRECT_URI\" >> ./local.properties + + # Create google-services.json + - name: Create google-services.json + run: | + cat << EOF > PennMobile/google-services.json + ${{ secrets.GOOGLE_SERVICES_JSON }} + EOF + # Run unit tests - name: Run Unit Tests run: ./gradlew testDebugUnitTest @@ -60,7 +68,14 @@ jobs: env: PLATFORM_REDIRECT_URI: ${{ secrets.PLATFORM_REDIRECT_URI }} run: echo PLATFORM_REDIRECT_URI=\"$PLATFORM_REDIRECT_URI\" >> ./local.properties - + + # Create google-services.json + - name: Create google-services.json + run: | + cat << EOF > PennMobile/google-services.json + ${{ secrets.GOOGLE_SERVICES_JSON }} + EOF + # Generate Signed APK - name: Generate Release APK run: ./gradlew assembleRelease @@ -108,6 +123,13 @@ jobs: PLATFORM_REDIRECT_URI: ${{ secrets.PLATFORM_REDIRECT_URI }} run: echo PLATFORM_REDIRECT_URI=\"$PLATFORM_REDIRECT_URI\" >> ./local.properties + # Create google-services.json + - name: Create google-services.json + run: | + cat << EOF > PennMobile/google-services.json + ${{ secrets.GOOGLE_SERVICES_JSON }} + EOF + # Run JaCoCo, generate Test Report - name: Check Code Coverage run: ./gradlew jacocoTestReport --stacktrace @@ -120,6 +142,7 @@ jobs: path: PennMobile/build/reports # Publish to Firebase App Distribution + # https://github.com/wzieba/Firebase-Distribution-Github-Action deploy-firebase: needs: generate-apk if: startsWith(github.ref, 'refs/tags/v') @@ -132,7 +155,7 @@ jobs: uses: wzieba/Firebase-Distribution-Github-Action@v1 with: appId: ${{secrets.FIREBASE_APP_ID}} - token: ${{secrets.FIREBASE_TOKEN}} + serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }} groups: tester file: PennMobile-release-unsigned-signed.apk diff --git a/.gitignore b/.gitignore index feecd6d8..bf293e5c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ gradle/wrapper/ # Local configuration file (sdk path, etc) local.properties +google-services.json # Proguard folder generated by Eclipse proguard/ diff --git a/PennMobile/build.gradle b/PennMobile/build.gradle index 9065e10d..13987158 100644 --- a/PennMobile/build.gradle +++ b/PennMobile/build.gradle @@ -2,6 +2,7 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' id 'com.google.gms.google-services' + id("com.google.firebase.crashlytics") id 'jacoco' } @@ -42,6 +43,8 @@ dependencies { implementation(platform("com.google.firebase:firebase-bom:31.5.0")) implementation 'com.google.firebase:firebase-analytics' + implementation("com.google.firebase:firebase-crashlytics") + implementation 'androidx.multidex:multidex:2.0.1' implementation 'com.google.maps:google-maps-services:2.2.0' implementation 'org.jsoup:jsoup:1.16.2' @@ -68,6 +71,7 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.daimajia.swipelayout:library:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.google.firebase:firebase-crashlytics-ktx:18.6.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'org.testng:testng:7.8.0' implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/DiningFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/DiningFragment.kt index fe7ef2cf..c60deb0d 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/DiningFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/DiningFragment.kt @@ -39,12 +39,6 @@ class DiningFragment : Fragment() { mActivity = activity as MainActivity mActivity.closeKeyboard() setHasOptionsMenu(true) - - val bundle = Bundle() - bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "1") - bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "Dining") - bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "App Feature") - FirebaseAnalytics.getInstance(mActivity).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle) } override fun onActivityCreated(savedInstanceState: Bundle?) { diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/FlingFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/FlingFragment.kt index 4608d640..13e15312 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/FlingFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/FlingFragment.kt @@ -24,12 +24,6 @@ class FlingFragment : Fragment() { setHasOptionsMenu(true) mActivity = activity as MainActivity mActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true) - - val bundle = Bundle() - bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "7") - bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "Spring Fling") - bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "App Feature") - FirebaseAnalytics.getInstance(mActivity).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle) } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/GsrFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/GsrFragment.kt index d5cbff37..e10feeb1 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/GsrFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/GsrFragment.kt @@ -78,12 +78,6 @@ class GsrFragment : Fragment() { // set default GSR selection date + time to the current date and time selectedDateTime = DateTime.now() - - val bundle = Bundle() - bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "0") - bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "GSR") - bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "App Feature") - FirebaseAnalytics.getInstance(mActivity).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/GsrReservationsFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/GsrReservationsFragment.kt index a1bb5604..0db3f054 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/GsrReservationsFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/GsrReservationsFragment.kt @@ -33,12 +33,6 @@ class GsrReservationsFragment : Fragment() { mActivity = activity as MainActivity LocalBroadcastManager.getInstance(mActivity).registerReceiver(broadcastReceiver, IntentFilter("refresh")) - - val bundle = Bundle() - bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "10") - bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "GsrReservations") - bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "App Feature") - FirebaseAnalytics.getInstance(mActivity).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/HomeFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/HomeFragment.kt index 6addc832..7e342b83 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/HomeFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/HomeFragment.kt @@ -20,7 +20,6 @@ import androidx.lifecycle.repeatOnLifecycle import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.preference.PreferenceManager import androidx.recyclerview.widget.LinearLayoutManager -import com.google.firebase.analytics.FirebaseAnalytics import com.pennapps.labs.pennmobile.adapters.HomeAdapter import com.pennapps.labs.pennmobile.api.OAuth2NetworkManager import com.pennapps.labs.pennmobile.classes.HomepageViewModel @@ -34,7 +33,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.* - class HomeFragment : Fragment() { private lateinit var mActivity: MainActivity @@ -53,13 +51,6 @@ class HomeFragment : Fragment() { LocalBroadcastManager .getInstance(mActivity) .registerReceiver(broadcastReceiver, IntentFilter("refresh")) - - val bundle = Bundle() - bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "11") - bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "Home") - bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "App Feature") - FirebaseAnalytics.getInstance(mActivity).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle) - } override fun onCreateView( diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LaundrySettingsFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LaundrySettingsFragment.kt index 0f28a9c8..0b56159e 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LaundrySettingsFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LaundrySettingsFragment.kt @@ -44,12 +44,6 @@ class LaundrySettingsFragment : Fragment() { //setHasOptionsMenu(true) mActivity.toolbar.visibility = View.VISIBLE mActivity.hideBottomBar() - - val bundle = Bundle() - bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "12") - bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "Laundry Settings") - bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "App Feature") - FirebaseAnalytics.getInstance(mContext).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { @@ -68,10 +62,8 @@ class LaundrySettingsFragment : Fragment() { editor?.apply() for (i in 0 until numRooms) { - editor?.remove(Integer.toString(i))?.apply() + editor?.remove(i.toString())?.apply() } - - //view.laundry_building_expandable_list?.setAdapter(mAdapter) } // set up back button diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LoginFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LoginFragment.kt index fac99e7b..b3c81189 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LoginFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LoginFragment.kt @@ -34,9 +34,6 @@ class LoginFragment : Fragment() { val fragmentManager = mActivity.supportFragmentManager val gif = R.drawable.login_background -// if (Build.VERSION.SDK_INT > 28 && (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES) { -// gif = R.drawable.login_background_dark -// } Glide.with(this).asGif().load(gif).listener(object : RequestListener { override fun onLoadFailed(e: GlideException?, model: Any?, target: com.bumptech.glide.request.target.Target?, isFirstResource: Boolean): Boolean { diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LoginWebviewFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LoginWebviewFragment.kt index 82c730e1..a09422c9 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LoginWebviewFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/LoginWebviewFragment.kt @@ -15,6 +15,8 @@ import android.widget.LinearLayout import android.widget.Toast import androidx.fragment.app.Fragment import androidx.preference.PreferenceManager +import com.google.firebase.analytics.FirebaseAnalytics +import com.google.firebase.crashlytics.FirebaseCrashlytics import com.pennapps.labs.pennmobile.api.StudentLife import com.pennapps.labs.pennmobile.api.Platform import com.pennapps.labs.pennmobile.api.Platform.platformBaseUrl @@ -89,7 +91,6 @@ class LoginWebviewFragment : Fragment() { cancelButton.setOnClickListener { mActivity.startLoginFragment() } - } private fun encryptPassword(password: String) { @@ -164,6 +165,9 @@ class LoginWebviewFragment : Fragment() { override fun success(t: AccessTokenResponse?, response: Response?) { if (response?.status == 200) { + + FirebaseAnalytics.getInstance(mActivity).logEvent("LoginEvent", null) + val accessToken = t?.accessToken val editor = sp.edit() editor.putString(getString(R.string.access_token), accessToken) @@ -180,6 +184,7 @@ class LoginWebviewFragment : Fragment() { } override fun failure(error: RetrofitError) { + FirebaseCrashlytics.getInstance().recordException(error) Log.e("Accounts", "Error fetching access token $error", error) Toast.makeText(mActivity, "Error logging in", Toast.LENGTH_SHORT).show() mActivity.startLoginFragment() diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.kt index 466c9df9..45c44648 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.kt @@ -30,6 +30,7 @@ import androidx.preference.PreferenceManager import androidx.viewpager.widget.ViewPager import com.google.android.material.appbar.AppBarLayout import com.google.android.material.tabs.TabLayout +import com.google.firebase.analytics.FirebaseAnalytics import com.google.gson.GsonBuilder import com.google.gson.reflect.TypeToken import com.pennapps.labs.pennmobile.adapters.MainPagerAdapter @@ -52,12 +53,14 @@ import retrofit.client.OkClient import retrofit.converter.GsonConverter import java.util.concurrent.TimeUnit + class MainActivity : AppCompatActivity() { private var tabShowed = false private lateinit var fragmentManager: FragmentManager private lateinit var mSharedPrefs: SharedPreferences val tokenMutex = Mutex() + private lateinit var mFirebaseAnalytics: FirebaseAnalytics val mNetworkManager by lazy { OAuth2NetworkManager(this) } override fun onCreate(savedInstanceState: Bundle?) { @@ -90,6 +93,9 @@ class MainActivity : AppCompatActivity() { showBottomBar() supportActionBar?.setDisplayShowTitleEnabled(false) + mFirebaseAnalytics = FirebaseAnalytics.getInstance(this); + mFirebaseAnalytics.logEvent("MainActivityStart", null) + // Show HomeFragment if logged in, otherwise show LoginFragment val pennKey = mSharedPrefs.getString(getString(R.string.pennkey), null) val guestMode = mSharedPrefs.getBoolean(getString(R.string.guest_mode), false) diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/NewsFragment.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/NewsFragment.kt index 2e8d09ed..47d7acfd 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/NewsFragment.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/NewsFragment.kt @@ -139,13 +139,7 @@ class NewsFragment : ListFragment() { mActivity.closeKeyboard() setHasOptionsMenu(true) - val bundle = Bundle() - bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "5") - bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "News") - bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "App Feature") - FirebaseAnalytics.getInstance(mActivity).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle) sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mActivity) - } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/DiningInsightsCardAdapter.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/DiningInsightsCardAdapter.kt index 2e5b5524..d0acf9c9 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/DiningInsightsCardAdapter.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/DiningInsightsCardAdapter.kt @@ -45,8 +45,8 @@ class DiningInsightsCardAdapter(private var cells: ArrayList) private const val DINING_DOLLARS_PREDICTIONS = 2 private const val DINING_SWIPES_PREDICTIONS = 3 - const val START_DAY_OF_SEMESTER = "2023-08-30" - private const val DAYS_IN_SEMESTER = 113f + const val START_DAY_OF_SEMESTER = "2024-01-18" + private const val DAYS_IN_SEMESTER = 117f } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/OAuth2NetworkManager.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/OAuth2NetworkManager.kt index c655456f..7834dad0 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/OAuth2NetworkManager.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/OAuth2NetworkManager.kt @@ -4,6 +4,8 @@ import androidx.preference.PreferenceManager import android.provider.Settings import android.util.Log import androidx.lifecycle.lifecycleScope +import com.google.firebase.crashlytics.FirebaseCrashlytics + import com.pennapps.labs.pennmobile.BuildConfig import com.pennapps.labs.pennmobile.MainActivity import com.pennapps.labs.pennmobile.R @@ -80,6 +82,7 @@ class OAuth2NetworkManager(private var mActivity: MainActivity) { override fun failure(error: RetrofitError) { + FirebaseCrashlytics.getInstance().recordException(error) Log.e("Accounts", "Error refreshing access token $error") if (error.response != null && error.response.status == 400) { diff --git a/build.gradle b/build.gradle index 20e1c1ca..0594e417 100644 --- a/build.gradle +++ b/build.gradle @@ -4,4 +4,5 @@ plugins { id 'com.android.library' version '8.0.2' apply false id 'org.jetbrains.kotlin.android' version '1.7.22' apply false id 'com.google.gms.google-services' version "4.4.0" apply false + id("com.google.firebase.crashlytics") version "2.9.9" apply false } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7f681c19..fefc185e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Nov 01 14:54:54 EDT 2023 +#Fri Dec 01 16:55:01 EST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists