我从多个网站收到Chrome通知,当我什至没有为这些网站打开任何标签时,它们就会起作用。
但是有时当我不在办公桌旁或看着笔记本电脑时,会收到这些Chrome通知。
由于其中一些通知对我有用,因此我希望能够访问任何我错过的内容。
有没有办法查看通知历史记录?
chrome://notifications
并且它们也没有进入操作系统。
我从多个网站收到Chrome通知,当我什至没有为这些网站打开任何标签时,它们就会起作用。
但是有时当我不在办公桌旁或看着笔记本电脑时,会收到这些Chrome通知。
由于其中一些通知对我有用,因此我希望能够访问任何我错过的内容。
有没有办法查看通知历史记录?
chrome://notifications
并且它们也没有进入操作系统。
Answers:
如果您使用的是Mac,那就有办法了!😄
通知列表如下所示:
您所需要做的就是:
1.在Chrome浏览器中,转到:
chrome://flags/
2.寻找:
Enable native notifications. Mac
3.启用它,重新启动chrome,就完成了。请享用!
编辑:
从Chrome 59开始,通过Notifications API或chrome.notifications扩展API发送的通知将直接由macOS本机通知系统显示,而不是由Chrome本身的系统显示。[ 来源 ]
在MacOSX上,您将在“库/应用程序支持”中找到Chrome目录。打开终端应用程序并运行以下命令:
cd ~/Library/Application\ Support/Google/Chrome/Default/Platform\ Notifications/
ls -la
现在您将看到如下文件:
drwx------@ 7 visi staff 224 Jul 13 18:16 .
drwx------ 75 visi staff 2400 Jul 15 11:05 ..
-rw-------@ 1 visi staff 759 Jul 15 10:57 000003.log
-rw-------@ 1 visi staff 16 Jul 13 18:16 CURRENT
-rw-------@ 1 visi staff 0 Jul 13 18:16 LOCK
-rw-------@ 1 visi staff 147 Jul 13 18:16 LOG
-rw-------@ 1 visi staff 41 Jul 13 18:16 MANIFEST-000001
您可以看到最新的是000003.log,因此请使用下一条命令进行检查:
tail -n 100 000003.log
您将在此日志中看到最后100个项目。然后,您可以打开Chrome设置并禁用该网站通知。
请注意,如果您在Chrome中有多个配置文件,则您的路径可以不同,如下所示(Profile1而非Default):
cd ~/Library/Application\ Support/Google/Chrome/Profile\ 1/Platform\ Notifications/
如果转到%LocalAppData%\Google\Chrome\User Data\Default\Platform Notifications
,则将有一个过去通知的日志文件。
由于似乎无法直接获得通知的记录,因此,如果我遇到相同的问题,我会以推荐使用Pushbullet的用户的身份使用Android手机仿真器或电话来作弊。但是不仅有Pushbullet,还有很多其他应用程序,我们可以在一个单独的线程中讨论android技巧来侦听和记录通知。
如果您是一名程序员,则可以通过自制扩展程序解决问题:
https://stackoverflow.com/questions/15949606/how-can-i-listen-to-notifications
“您可以挂钩webkitNotifications.createNotification函数,以便无论何时创建通知,您都将运行一些特定的代码。”
似乎Pushbullet可以解决您的问题。他们声称您可以使用其Chrome扩展程序看到错过的通知。
https://blog.pushbullet.com/2014/10/23/easily-access-your-recent-notifications-in-chrome/
多亏了Corey的上述回答,以及一个懒惰的星期六,我手忙脚乱,现在我可以在IDE的控制台中看到最近的Chrome通知列表,甚至可以单击URL。
由于我不了解解释二进制数据的正确方法,因此代码很糟糕,并使用了粗略的启发式方法。
但它是一吨比没有好。输出示例(节选):
https://www.finanzen.net/nachricht/aktien/kw-9-tops-und-flops-der-tecdax-aktien-in-der-vergangenen-woche-7195100
https://images.finanzen.net/mediacenter/unsortiert/TecDAX_boerse_frankfurt0016_kl.jpg
So bewegten sich die Einzelwerte des TecDAX in der zurückliegenden Handelswoche.*
KW 9: Tops und Flops der TecDAX-Aktien in der vergangenen Woche
So bewegten sich die Einzelwerte des TecDAX in der zurückliegenden Handelswoche.
HideOnTheseRoutes
Home/Index;Article/News/Index
tag-7195100
NotificationIdentifier
1061622960{
https://www.youtube.com/watch?v=W-mlD_bYKdU&feature=push-u-sub&attr_tag=0SL8UpnrTOnTECxr%3A6
https://lh5.googleusercontent.com/-raJM5SITO34/AAAAAAAAAAI/AAAAAAAAAAA/UtLljlL4Wpc/s96-c-mo/photo.jpg
New from Market Moves
Trade Recap: $1,500 in PROFITS*˜
COuAyJGY4uACEAY=
attributionTag
0SL8UpnrTOnTECxr:6{
from Market MovesTrade Recap: $1,500 in PROFITS
值得钉十字架的Java代码:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
/**
* v[1, 2019-03-02 13:00 UTC]
*
* by dreamspace-president.com
*/
final public class CrappyChromeNotificationHistoryReader {
public static void main(final String[] args) {
final File file = new File(
"C:\\Users\\[YOUR_NAME_HERE]\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Platform Notifications\\000003.log");
final List<ChromeNotificationStuff> notifications = obtainChromeNotificationStuff(file);
for (ChromeNotificationStuff notification : notifications) {
System.err.println();
System.err.println(notification);
}
System.exit(0);
}
public static List<ChromeNotificationStuff> obtainChromeNotificationStuff(final File file) {
final List<ChromeNotificationStuff> ret = new ArrayList<>();
final List<DumbTokenList> listOfDumbTokenLists = doTheInsaneParsingThing(file);
int instanceCounter = 0;
for (DumbTokenList dtl : listOfDumbTokenLists) {
final List<String> urls = new ArrayList<>();
final List<String> texts = new ArrayList<>();
for (String token : dtl.tokens) {
if (token.startsWith("https://") || token.startsWith("http://")) {
urls.add(token);
} else {
texts.add(token);
}
}
// Remove unimportant URLs.
for (int i = urls.size() - 1; i > 0; i--) {
final String urlThis = urls.get(i);
final int lenThis = urlThis.length();
for (int ii = i - 1; ii >= 0; ii--) {
final String urlThat = urls.get(ii);
final int lenThat = urlThat.length();
if (lenThis > lenThat) {
if (urlThis.startsWith(urlThat)) {
final String removed = urls.remove(ii);
// System.err.println("\nREMOVED: " + removed + "\nKEPT : " + urlThis); // because was better or equal
break;
}
} else {
if (urlThat.startsWith(urlThis)) {
final String removed = urls.remove(i);
// System.err.println("\nREMOVED: " + removed + "\nKEPT : " + urlThat); // because was better or equal
break;
}
}
}
}
ret.add(new ChromeNotificationStuff(instanceCounter, urls, texts));
instanceCounter++;
}
ret.sort(null);
return ret;
}
final public static class ChromeNotificationStuff implements Comparable<ChromeNotificationStuff> {
private final int instanceCounter;
final public List<String> urls;
final public List<String> texts;
private ChromeNotificationStuff(final int instanceCounter,
final List<String> urls,
final List<String> texts) {
this.instanceCounter = instanceCounter;
this.urls = Collections.unmodifiableList(urls);
this.texts = Collections.unmodifiableList(texts);
}
public String toString() {
final StringBuilder sb = new StringBuilder();
for (String url : urls) {
sb.append(url).append('\n');
}
for (String text : texts) {
sb.append(text).append('\n');
}
return sb.toString();
}
@Override
public int compareTo(final ChromeNotificationStuff o) { // Newest (= last) notifications first, please.
return Integer.compare(o.instanceCounter, instanceCounter);
}
}
final private static double MIN_LENGTH_DIFFERENCE_RATIO = 0.7;//0.9;
final private static double MIN_REMAININGLINES_PERCENTAGEOF_ALLLINES = 0.2;
final private static class DumbTokenList {
final private static int MIN_LENGTH = 10; //6;
final private static String[] EXTENSIONS = new String[] { ".jpg", ".jpeg", ".png", ".gif", ".html", ".htm", ".php" };
final private static int MAX_EXTRA_CRAP_AFTER_EXTENSIONS = 3;
final private static String SAFE_URL_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;="; // https://stackoverflow.com/a/1547940/3500521
final private String originalText;
final private List<String> tokens;
private DumbTokenList(final String textWithBinaryCrap) {
originalText = textWithBinaryCrap;
final List<String> tokens = new ArrayList<>();
final Consumer<String> addTokenButTryToDecrappifyExtensionsFirstAnTing = token -> {
if (token.startsWith("ttps://") || token.startsWith("ttp://")) {
token = "h" + token;
}
final List<String> newTokens = new ArrayList<>();
if (token.startsWith("http")) {
final int tokenLength = token.length();
boolean found = false;
for (int i = 0; i < tokenLength; i++) {
final char c = token.charAt(i);
if (SAFE_URL_CHARACTERS.indexOf(c) < 0) {
newTokens.add(token.substring(0, i));
newTokens.add(token.substring(i));
found = true;
break;
}
}
if (!found) {
newTokens.add(token);
}
} else {
newTokens.add(token);
}
for (String newToken : newTokens) {
String foundExt = null;
int foundExtLen = 0;
int foundExtAt = -1;
for (String extension : EXTENSIONS) {
final int idx = newToken.indexOf(extension);
if (idx >= 0) {
final int extLen = extension.length();
if (idx > foundExtAt || (idx == foundExtAt && extLen > foundExtLen)) {
foundExt = extension;
foundExtLen = extLen;
foundExtAt = idx;
}
}
}
if (foundExt != null) {
final int amountOfCharactersAfterThisFind = newToken.length() - foundExtAt - foundExtLen;
if (amountOfCharactersAfterThisFind <= MAX_EXTRA_CRAP_AFTER_EXTENSIONS) {
// OK. Shorten this bitch.
newToken = newToken.substring(0, foundExtAt + foundExtLen);
}
}
if (newToken.startsWith("http")) {
if (!newToken.startsWith("http://") && !newToken.startsWith("https://")) {
continue;
}
}
if (newToken.startsWith("/watch?v=")) {
newToken = "https://www.youtube.com" + newToken;
}
if (newToken.length() >= MIN_LENGTH) {
tokens.add(newToken);
}
}
};
final StringBuilder sb = new StringBuilder();
final int len = textWithBinaryCrap.length();
for (int i = 0; i <= len + 1; i++) {
final char c = i < len ? textWithBinaryCrap.charAt(i) : 0;
if (c < ' ' || c == '"') {
String potentialText = sb.toString();
while (true) {
final int httpIDX = potentialText.indexOf("http", 1);
if (httpIDX < 0) {
addTokenButTryToDecrappifyExtensionsFirstAnTing.accept(potentialText);
break;
} else {
final String snippet = potentialText.substring(0, httpIDX);
potentialText = potentialText.substring(httpIDX);
addTokenButTryToDecrappifyExtensionsFirstAnTing.accept(snippet);
}
}
sb.setLength(0);
if (c == '"') {
// Skip this and the next. (thus "i < len +1")
i++;
}
} else {
sb.append(c);
}
}
// Remove quasi-duplicates. Sue me.
// System.err.println("\n*** STARTING DEDUPLICATION ***");
final int lSize = tokens.size();
for (int i = lSize - 1; i > 0; i--) { // (not 0 itself, wouldn't make sense)
if (i < tokens.size()) {
final String entry = tokens.get(i);
for (int ii = i - 1; ii >= 0; ii--) { // (incl. 0)
final String otherEntry = tokens.get(ii);
final Boolean removeNoneOrFirstOrSecond = areLinesTooSimilar(entry, otherEntry);
if (removeNoneOrFirstOrSecond != null) {
if (!removeNoneOrFirstOrSecond) {
final String removed = tokens.remove(i);
// System.err.println("\nREMOVED: " + removed + "\nKEPT : " + otherEntry); // because was better or equal
} else {
final String removed = tokens.remove(ii);
// System.err.println("\nREMOVED: " + removed + "\nKEPT : " + entry); // because was better or equal
}
break; // IMPORTANT!
}
}
}
}
this.tokens = Collections.unmodifiableList(tokens);
}
public String toString() {
final StringBuilder sb = new StringBuilder();
for (String token : tokens) {
sb.append(token).append('\n');
}
return sb.toString();
}
}
/**
* Do NOT call with NULL/EMPTY arguments.
*
* @return NULL if not too similar. False if the FIRST seems superfluous. True if the SECOND seems superfluous.
*/
private static Boolean areLinesTooSimilar(final String line1,
final String line2) {
final int l1 = line1.length();
final int l2 = line2.length();
final double lenDiffRatio = Math.min(l1, l2) / (double) Math.max(l1, l2); // Results in 1 or less.
if (lenDiffRatio >= MIN_LENGTH_DIFFERENCE_RATIO) {
if (l2 < l1) {
// Compare the other way round.
if (line1.contains(line2)) {
return false;
}
} else {
if (line2.contains(line1)) {
return true;
}
}
}
return null;
}
private static List<DumbTokenList> doTheInsaneParsingThing(final File file) {
final List<DumbTokenList> ret = new ArrayList<>();
final StringBuilder sb = new StringBuilder();
try (final InputStream is = new BufferedInputStream(new FileInputStream(file))) {
final int bufMinus1 = 4;
final Charset charset = Charset.forName("Cp1252"); // =ansi
final int[] buf = new int[bufMinus1 + 1]; // "DATA"
// while ((buf[buf.length - 1] = is.read()) >= 0) {
while (true) {
buf[bufMinus1] = is.read();
if (buf[bufMinus1] < 0 || (
buf[0] == 'D' &&
buf[1] == 'A' &&
buf[2] == 'T' &&
buf[3] == 'A' &&
buf[4] == ':')) {
if (sb.length() > 0) {
ret.add(new DumbTokenList(sb.toString()));
sb.setLength(0);
}
if (buf[bufMinus1] < 0) {
break;
}
} else {
sb.append(new String(new byte[] { (byte) buf[bufMinus1] }, charset));
// sb.append((char) buf[bufMinus1]);
}
// Shift minibuffer to front.
for (int i = 0; i < bufMinus1; i++) {
buf[i] = buf[i + 1];
}
}
} catch (IOException e) {
e.printStackTrace();
}
// DEDUPLICATE DTLs
for (int i = ret.size() - 1; i > 0; i--) {
if (i < ret.size()) {
final DumbTokenList dtlThis = ret.get(i);
final int dtlThisTokenCount = dtlThis.tokens.size();
for (int ii = i - 1; ii >= 0; ii--) {
final DumbTokenList dtlThat = ret.get(ii);
final int dtlThatTokenCount = dtlThat.tokens.size();
int scoreViaRemainingLines_this = dtlThisTokenCount;
int scoreViaRemainingLines_that = dtlThatTokenCount;
for (int o = 0; o < dtlThisTokenCount; o++) {
final String tokenThis = dtlThis.tokens.get(o);
for (int oo = 0; oo < dtlThatTokenCount; oo++) {
final String tokenThat = dtlThat.tokens.get(oo);
final Boolean tooSimilar = areLinesTooSimilar(tokenThis, tokenThat);
if (tooSimilar != null) {
scoreViaRemainingLines_this--;
scoreViaRemainingLines_that--;
break;
}
}
}
if (scoreViaRemainingLines_this < 0 || scoreViaRemainingLines_that < 0) {
throw new Error();
}
final double scoreActual_this = scoreViaRemainingLines_this / (double) dtlThisTokenCount;
final double scoreActual_that = scoreViaRemainingLines_that / (double) dtlThatTokenCount;
if (scoreViaRemainingLines_this < scoreViaRemainingLines_that) {
if (scoreActual_this < MIN_REMAININGLINES_PERCENTAGEOF_ALLLINES) {
final DumbTokenList removed = ret.remove(i);
// System.err.println("\nREMOVED:\n" + removed + "\nKEPT :\n" + dtlThat);
break; // IMPORTANT.
}
} else {
if (scoreActual_that < MIN_REMAININGLINES_PERCENTAGEOF_ALLLINES) {
final DumbTokenList removed = ret.remove(ii);
// System.err.println("\nREMOVED:\n" + removed + "\nKEPT :\n" + dtlThis);
break; // IMPORTANT.
}
}
}
}
}
return ret;
}
}
javac "C:\Users\MLM\Downloads\CrappyChromeNotificationHistoryReader.java"
((编译)和 java -cp C:\Users\MLM\Downloads CrappyChromeNotificationHistoryReader
(运行)):脚本失败了,if (scoreViaRemainingLines_this < 0 || scoreViaRemainingLines_that < 0) {
所以我注释掉了所有解析,doTheInsaneParsingThing
并System.out.println(sb.toString());
在将令牌添加到列表中时打印了所有内容。看起来“平台通知”仅处理服务器工作程序推送通知。