-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
App update notification #1608
Merged
Merged
App update notification #1608
Changes from 37 commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
75a44fb
Added HTTPS request to get version data. Added APK flaor for github a…
krtkush 5e2aa51
Moved the asynctask to its own class.
krtkush f85e19c
Added notification channel and code to show notification.
krtkush 7c875a8
Merge branch 'dev' of https://github.com/krtkush/NewPipe into 1520_ap…
krtkush 06f20c6
Moved the new version check to the application class.
krtkush 930c971
Added version check in the pop-up player
krtkush 12b93d6
Added new icon for update notification.
krtkush af42e32
Code refactored and added comments.
krtkush 2a18eac
More refactoring.
krtkush e7abeb5
Added version code check.
krtkush 04e974b
Bug fix.
krtkush 910c10f
Removed debug code
krtkush 17197ad
Pull request changes begins here.
krtkush 395c958
Conflict resolution.
krtkush cde5f7d
Merge branch 'dev' of https://github.com/krtkush/NewPipe into 1520_ap…
krtkush 6417bd9
Pull request changes v1.
krtkush 7124d9b
Removed flvor checks. Added update settings under main settings.
krtkush f1aa3d8
Merge branch 'dev' into 1520_app_update_notif
theScrabi e234136
Added check for SHA1 key.
krtkush 54ac5e8
Merge branch '1520_app_update_notif' of https://github.com/krtkush/Ne…
krtkush 8ef702f
Removed updates options from settings in case of non github apk.
krtkush 506ffb9
Delete BuildConfig.java
krtkush 2d5bc3a
Delete Manifest.java
krtkush d1a9033
Delete R.java
krtkush ec28e97
Delete BuildConfig.java
krtkush 6ef25eb
Delete Manifest.java
krtkush 3c6d27b
Delete R.java
krtkush fda9b59
Code review changes.
TobiGr 96dac0f
Code review suggested changes.
krtkush c29b064
Merge branch '1520_app_update_notif' of https://github.com/krtkush/Ne…
krtkush 23309e6
Pull request changes.
krtkush 939cc56
Pull request changes v2.
krtkush ad5535a
Code refactoring, PR changes.
krtkush 26e22f9
Conflict resolution
krtkush 069654c
vector -> png
krtkush c864b15
Test code revert.
krtkush 7ed460c
Merge branch 'dev' into 1520_app_update_notif
krtkush f62bfea
Merge branch 'dev' into 1520_app_update_notif
TobiGr bfda8dc
Merge branch 'dev' into 1520_app_update_notif
krtkush 67499bd
Merge branch 'dev' into 1520_app_update_notif
krtkush b674006
Conflict resolution.
krtkush 794c370
Merge branch '1520_app_update_notif' of https://github.com/krtkush/Ne…
krtkush File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
230 changes: 230 additions & 0 deletions
230
app/src/main/java/org/schabi/newpipe/CheckForNewAppVersionTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package org.schabi.newpipe; | ||
|
||
import android.app.Application; | ||
import android.app.PendingIntent; | ||
import android.content.Intent; | ||
import android.content.SharedPreferences; | ||
import android.content.pm.PackageInfo; | ||
import android.content.pm.PackageManager; | ||
import android.content.pm.Signature; | ||
import android.net.Uri; | ||
import android.os.AsyncTask; | ||
import android.preference.PreferenceManager; | ||
import android.support.v4.app.NotificationCompat; | ||
import android.support.v4.app.NotificationManagerCompat; | ||
|
||
import org.json.JSONException; | ||
import org.json.JSONObject; | ||
import org.schabi.newpipe.report.ErrorActivity; | ||
import org.schabi.newpipe.report.UserAction; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.ByteArrayInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.net.HttpURLConnection; | ||
import java.net.URL; | ||
import java.security.MessageDigest; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.security.cert.CertificateEncodingException; | ||
import java.security.cert.CertificateException; | ||
import java.security.cert.CertificateFactory; | ||
import java.security.cert.X509Certificate; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import okhttp3.OkHttpClient; | ||
import okhttp3.Request; | ||
import okhttp3.RequestBody; | ||
import okhttp3.Response; | ||
|
||
/** | ||
* AsyncTask to check if there is a newer version of the NewPipe github apk available or not. | ||
* If there is a newer version we show a notification, informing the user. On tapping | ||
* the notification, the user will be directed to the download link. | ||
*/ | ||
public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> { | ||
|
||
private static final Application app = App.getApp(); | ||
private static final String GITHUB_APK_SHA1 = "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15"; | ||
private static final String newPipeApiUrl = "https://newpipe.schabi.org/api/data.json"; | ||
private static final int timeoutPeriod = 30; | ||
|
||
private SharedPreferences mPrefs; | ||
private OkHttpClient client; | ||
|
||
@Override | ||
protected void onPreExecute() { | ||
|
||
mPrefs = PreferenceManager.getDefaultSharedPreferences(app); | ||
|
||
// Check if user has enabled/ disabled update checking | ||
// and if the current apk is a github one or not. | ||
if (!mPrefs.getBoolean(app.getString(R.string.update_app_key), true) | ||
|| !isGithubApk()) { | ||
this.cancel(true); | ||
} | ||
} | ||
|
||
@Override | ||
protected String doInBackground(Void... voids) { | ||
|
||
// Make a network request to get latest NewPipe data. | ||
if (client == null) { | ||
|
||
client = new OkHttpClient | ||
.Builder() | ||
.readTimeout(timeoutPeriod, TimeUnit.SECONDS) | ||
.build(); | ||
} | ||
|
||
Request request = new Request.Builder() | ||
.url(newPipeApiUrl) | ||
.build(); | ||
|
||
try { | ||
Response response = client.newCall(request).execute(); | ||
return response.body().string(); | ||
} catch (IOException ex) { | ||
krtkush marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ErrorActivity.reportError(app, ex, null, null, | ||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", | ||
"app update API fail", R.string.app_ui_crash)); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
@Override | ||
protected void onPostExecute(String response) { | ||
|
||
// Parse the json from the response. | ||
if (response != null) { | ||
|
||
try { | ||
JSONObject mainObject = new JSONObject(response); | ||
JSONObject flavoursObject = mainObject.getJSONObject("flavors"); | ||
JSONObject githubObject = flavoursObject.getJSONObject("github"); | ||
JSONObject githubStableObject = githubObject.getJSONObject("stable"); | ||
|
||
String versionName = githubStableObject.getString("version"); | ||
String versionCode = githubStableObject.getString("version_code"); | ||
String apkLocationUrl = githubStableObject.getString("apk"); | ||
|
||
compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode); | ||
|
||
} catch (JSONException ex) { | ||
ErrorActivity.reportError(app, ex, null, null, | ||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", | ||
"could not parse app update JSON data", R.string.app_ui_crash)); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Method to compare the current and latest available app version. | ||
* If a newer version is available, we show the update notification. | ||
* @param versionName | ||
* @param apkLocationUrl | ||
*/ | ||
private void compareAppVersionAndShowNotification(String versionName, | ||
String apkLocationUrl, | ||
String versionCode) { | ||
|
||
int NOTIFICATION_ID = 2000; | ||
|
||
if (BuildConfig.VERSION_CODE < Integer.valueOf(versionCode)) { | ||
|
||
// A pending intent to open the apk location url in the browser. | ||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl)); | ||
PendingIntent pendingIntent | ||
= PendingIntent.getActivity(app, 0, intent, 0); | ||
|
||
NotificationCompat.Builder notificationBuilder = new NotificationCompat | ||
.Builder(app, app.getString(R.string.app_update_notification_channel_id)) | ||
.setSmallIcon(R.drawable.ic_newpipe_update) | ||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) | ||
.setContentIntent(pendingIntent) | ||
.setAutoCancel(true) | ||
.setContentTitle(app.getString(R.string.app_update_notification_content_title)) | ||
.setContentText(app.getString(R.string.app_update_notification_content_text) | ||
+ " " + versionName); | ||
|
||
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(app); | ||
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); | ||
} | ||
} | ||
|
||
/** | ||
* Method to get the apk's SHA1 key. | ||
* https://stackoverflow.com/questions/9293019/get-certificate-fingerprint-from-android-app#22506133 | ||
*/ | ||
private static String getCertificateSHA1Fingerprint() { | ||
|
||
PackageManager pm = app.getPackageManager(); | ||
String packageName = app.getPackageName(); | ||
int flags = PackageManager.GET_SIGNATURES; | ||
PackageInfo packageInfo = null; | ||
|
||
try { | ||
packageInfo = pm.getPackageInfo(packageName, flags); | ||
} catch (PackageManager.NameNotFoundException ex) { | ||
ErrorActivity.reportError(app, ex, null, null, | ||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", | ||
"Could not find package info", R.string.app_ui_crash)); | ||
} | ||
|
||
Signature[] signatures = packageInfo.signatures; | ||
byte[] cert = signatures[0].toByteArray(); | ||
InputStream input = new ByteArrayInputStream(cert); | ||
|
||
CertificateFactory cf = null; | ||
X509Certificate c = null; | ||
|
||
try { | ||
cf = CertificateFactory.getInstance("X509"); | ||
c = (X509Certificate) cf.generateCertificate(input); | ||
} catch (CertificateException ex) { | ||
ErrorActivity.reportError(app, ex, null, null, | ||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", | ||
"Certificate error", R.string.app_ui_crash)); | ||
} | ||
|
||
String hexString = null; | ||
|
||
try { | ||
MessageDigest md = MessageDigest.getInstance("SHA1"); | ||
byte[] publicKey = md.digest(c.getEncoded()); | ||
hexString = byte2HexFormatted(publicKey); | ||
} catch (NoSuchAlgorithmException ex1) { | ||
ErrorActivity.reportError(app, ex1, null, null, | ||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", | ||
"Could not retrieve SHA1 key", R.string.app_ui_crash)); | ||
} catch (CertificateEncodingException ex2) { | ||
ErrorActivity.reportError(app, ex2, null, null, | ||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", | ||
"Could not retrieve SHA1 key", R.string.app_ui_crash)); | ||
} | ||
|
||
return hexString; | ||
} | ||
|
||
private static String byte2HexFormatted(byte[] arr) { | ||
|
||
StringBuilder str = new StringBuilder(arr.length * 2); | ||
|
||
for (int i = 0; i < arr.length; i++) { | ||
String h = Integer.toHexString(arr[i]); | ||
int l = h.length(); | ||
if (l == 1) h = "0" + h; | ||
if (l > 2) h = h.substring(l - 2, l); | ||
str.append(h.toUpperCase()); | ||
if (i < (arr.length - 1)) str.append(':'); | ||
} | ||
return str.toString(); | ||
} | ||
|
||
public static boolean isGithubApk() { | ||
|
||
return getCertificateSHA1Fingerprint().equals(GITHUB_APK_SHA1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package org.schabi.newpipe.settings; | ||
|
||
import android.os.Bundle; | ||
import android.support.annotation.Nullable; | ||
import android.support.v7.preference.Preference; | ||
|
||
import org.schabi.newpipe.CheckForNewAppVersionTask; | ||
import org.schabi.newpipe.R; | ||
|
||
public class UpdateSettingsFragment extends BasePreferenceFragment { | ||
|
||
@Override | ||
public void onCreate(@Nullable Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | ||
|
||
String updateToggleKey = getString(R.string.update_app_key); | ||
findPreference(updateToggleKey).setOnPreferenceChangeListener(updatePreferenceChange); | ||
} | ||
|
||
@Override | ||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { | ||
addPreferencesFromResource(R.xml.update_settings); | ||
} | ||
|
||
private Preference.OnPreferenceChangeListener updatePreferenceChange | ||
= (preference, newValue) -> { | ||
|
||
defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), | ||
(boolean) newValue).apply(); | ||
|
||
return true; | ||
}; | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+431 Bytes
app/src/main/res/drawable/drawable-hdpi/ic_settings_update_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+379 Bytes
app/src/main/res/drawable/drawable-mdpi/ic_settings_update_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+710 Bytes
app/src/main/res/drawable/drawable-xhdpi/ic_settings_update_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.07 KB
app/src/main/res/drawable/drawable-xxhdpi/ic_settings_update_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.98 KB
app/src/main/res/drawable/drawable-xxxhdpi/ic_settings_update_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+431 Bytes
...es/drawable/ic_settings_update_black/drawable-hdpi/ic_settings_update_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+379 Bytes
...es/drawable/ic_settings_update_black/drawable-mdpi/ic_settings_update_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+710 Bytes
...s/drawable/ic_settings_update_black/drawable-xhdpi/ic_settings_update_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.07 KB
.../drawable/ic_settings_update_black/drawable-xxhdpi/ic_settings_update_black.png
Oops, something went wrong.
Binary file added
BIN
+1.98 KB
...drawable/ic_settings_update_black/drawable-xxxhdpi/ic_settings_update_black.png
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking this before starting the task would be more efficient, at App#L108
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is 4 years old code, is this still the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @Stypox,
I apologize for my previous comment. I didn't realize that the code was 4 years old, and I see that it has now been deleted. I was going through the code to explore and understand the codebase, but I should have been more careful about commenting on old code.
I'll be more mindful of the age of code in the future and avoid commenting on old code unless I'm sure it's still relevant.
Thanks for your patience and understanding.