mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-04 15:51:37 +00:00
Bug 867360 - Improve logging in watcher; r=jmaher
This commit is contained in:
parent
43760196c8
commit
578d1b9324
@ -49,7 +49,8 @@ import android.os.Environment;
|
||||
|
||||
public class WatcherService extends Service
|
||||
{
|
||||
private final String prgVersion = "Watcher Version 1.15";
|
||||
private final String prgVersion = "Watcher Version 1.16";
|
||||
private final String LOGTAG = "Watcher";
|
||||
|
||||
String sErrorPrefix = "##Installer Error## ";
|
||||
String currentDir = "/";
|
||||
@ -60,7 +61,7 @@ public class WatcherService extends Service
|
||||
boolean bStartSUTAgent = true;
|
||||
boolean bStartedTimer = false;
|
||||
|
||||
Process pProc;
|
||||
Process pProc;
|
||||
Context myContext = null;
|
||||
Timer myTimer = null;
|
||||
private PowerManager.WakeLock pwl = null;
|
||||
@ -69,12 +70,12 @@ public class WatcherService extends Service
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Class<?>[] mSetForegroundSignature = new Class[] {
|
||||
boolean.class};
|
||||
boolean.class};
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Class[] mStartForegroundSignature = new Class[] {
|
||||
private static final Class<?>[] mStartForegroundSignature = new Class[] {
|
||||
int.class, Notification.class};
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Class[] mStopForegroundSignature = new Class[] {
|
||||
private static final Class<?>[] mStopForegroundSignature = new Class[] {
|
||||
boolean.class};
|
||||
|
||||
private NotificationManager mNM;
|
||||
@ -103,6 +104,8 @@ public class WatcherService extends Service
|
||||
{
|
||||
super.onCreate();
|
||||
|
||||
Log.i(LOGTAG, prgVersion);
|
||||
|
||||
myContext = this;
|
||||
|
||||
getKeyGuardAndWakeLock();
|
||||
@ -112,7 +115,7 @@ public class WatcherService extends Service
|
||||
String sIniFile = iniFile.getAbsolutePath();
|
||||
String sHold = "";
|
||||
|
||||
Log.i("Watcher", String.format("Loading settings from %s", sIniFile));
|
||||
Log.i(LOGTAG, String.format("Loading settings from %s", sIniFile));
|
||||
this.sPingTarget = GetIniData("watcher", "PingTarget", sIniFile, "www.mozilla.org");
|
||||
sHold = GetIniData("watcher", "delay", sIniFile, "60000");
|
||||
this.lDelay = Long.parseLong(sHold.trim());
|
||||
@ -120,8 +123,8 @@ public class WatcherService extends Service
|
||||
this.lPeriod = Long.parseLong(sHold.trim());
|
||||
sHold = GetIniData("watcher", "strikes", sIniFile,"0");
|
||||
this.nMaxStrikes = Integer.parseInt(sHold.trim());
|
||||
Log.i("Watcher", String.format("Pinging %s after a delay of %s sec, period of %s sec, max number of failed attempts is %s (if max # of failed attempts is 0, then no checking)",
|
||||
this.sPingTarget, this.lDelay / 1000.0, this.lPeriod / 1000.0, nMaxStrikes));
|
||||
Log.i(LOGTAG, String.format("Pinging %s after a delay of %s sec, period of %s sec, max number of failed attempts is %s (if max # of failed attempts is 0, then no checking)",
|
||||
this.sPingTarget, this.lDelay / 1000.0, this.lPeriod / 1000.0, nMaxStrikes));
|
||||
|
||||
sHold = GetIniData("watcher", "StartSUTAgent", sIniFile, "true");
|
||||
this.bStartSUTAgent = Boolean.parseBoolean(sHold.trim());
|
||||
@ -151,7 +154,7 @@ public class WatcherService extends Service
|
||||
String sLine = "";
|
||||
boolean bFound = false;
|
||||
BufferedReader in = null;
|
||||
String sTmpFileName = fixFileName(sFile);
|
||||
String sTmpFileName = fixFileName(sFile);
|
||||
|
||||
try {
|
||||
in = new BufferedReader(new FileReader(sTmpFileName));
|
||||
@ -217,19 +220,20 @@ public class WatcherService extends Service
|
||||
String sOutFile = intent.getStringExtra("outFile");
|
||||
boolean bReboot = intent.getBooleanExtra("reboot", true);
|
||||
int nReboot = bReboot ? 1 : 0;
|
||||
SendNotification("WatcherService updating " + sPkgName + " using file " + sPkgFile, "WatcherService updating " + sPkgName + " using file " + sPkgFile);
|
||||
Log.i(LOGTAG, "WatcherService updating " + sPkgName + " using file " + sPkgFile);
|
||||
|
||||
UpdateApplication worker = new UpdateApplication(sPkgName, sPkgFile, sOutFile, nReboot);
|
||||
UpdateApplication worker = new UpdateApplication(sPkgName, sPkgFile, sOutFile, nReboot);
|
||||
}
|
||||
else if (sCmd.equalsIgnoreCase("start"))
|
||||
{
|
||||
if (!this.bStartedTimer) {
|
||||
if (!this.bStartedTimer)
|
||||
{
|
||||
doToast("WatcherService started");
|
||||
myTimer = new Timer();
|
||||
Date startSchedule = new Date(System.currentTimeMillis() + lDelay);
|
||||
myTimer.schedule(new MyTime(), startSchedule, lPeriod);
|
||||
this.bStartedTimer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -244,12 +248,12 @@ public class WatcherService extends Service
|
||||
PrintWriter pw = null;
|
||||
String appPath = getApplicationContext().getFilesDir().getAbsolutePath();
|
||||
String versionPath = appPath + "/version.txt";
|
||||
Log.i("Watcher", "writing version string to: " + versionPath);
|
||||
Log.i(LOGTAG, "writing version string to: " + versionPath);
|
||||
try {
|
||||
pw = new PrintWriter(new FileWriter(versionPath, true));
|
||||
pw.println(this.prgVersion);
|
||||
} catch (IOException ioe) {
|
||||
Log.e("Watcher", "Exception writing version: " + this.prgVersion + " to file: " + versionPath);
|
||||
Log.e(LOGTAG, "Exception writing version: " + this.prgVersion + " to file: " + versionPath);
|
||||
} finally {
|
||||
if (pw != null) {
|
||||
pw.close();
|
||||
@ -259,6 +263,7 @@ public class WatcherService extends Service
|
||||
|
||||
@Override
|
||||
public void onStart(Intent intent, int startId) {
|
||||
Log.i(LOGTAG, "onStart");
|
||||
writeVersion();
|
||||
handleCommand(intent);
|
||||
return;
|
||||
@ -266,10 +271,11 @@ public class WatcherService extends Service
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Log.i(LOGTAG, "onStartCommand");
|
||||
writeVersion();
|
||||
handleCommand(intent);
|
||||
return START_STICKY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
@ -285,13 +291,17 @@ public class WatcherService extends Service
|
||||
// Fire off a thread to do some work that we shouldn't do directly in the UI thread
|
||||
Thread t = new Thread() {
|
||||
public void run() {
|
||||
Log.i(LOGTAG, "worker thread started");
|
||||
// Keep phone from locking or remove lock on screen
|
||||
KeyguardManager km = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
|
||||
if (km != null)
|
||||
{
|
||||
KeyguardManager.KeyguardLock kl = km.newKeyguardLock("watcher");
|
||||
if (kl != null)
|
||||
{
|
||||
kl.disableKeyguard();
|
||||
Log.i(LOGTAG, "keyguard disabled");
|
||||
}
|
||||
}
|
||||
|
||||
// No sleeping on the job
|
||||
@ -300,7 +310,10 @@ public class WatcherService extends Service
|
||||
{
|
||||
pwl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "watcher");
|
||||
if (pwl != null)
|
||||
{
|
||||
pwl.acquire();
|
||||
Log.i(LOGTAG, "wake lock acquired");
|
||||
}
|
||||
}
|
||||
|
||||
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
||||
@ -310,14 +323,17 @@ public class WatcherService extends Service
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
// Running on an older platform.
|
||||
// Might be running on an older platform.
|
||||
mStartForeground = mStopForeground = null;
|
||||
Log.w(LOGTAG, "unable to find start/stopForeground method(s) -- older platform?");
|
||||
}
|
||||
try {
|
||||
mSetForeground = getClass().getMethod("setForeground", mSetForegroundSignature);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
mSetForeground = null;
|
||||
Log.e(LOGTAG, "unable to find setForeground method!");
|
||||
}
|
||||
Notification notification = new Notification();
|
||||
startForegroundCompat(R.string.foreground_service_started, notification);
|
||||
@ -337,12 +353,13 @@ public class WatcherService extends Service
|
||||
mStartForegroundArgs[1] = notification;
|
||||
try {
|
||||
mStartForeground.invoke(this, mStartForegroundArgs);
|
||||
Log.i(LOGTAG, "startForeground invoked");
|
||||
} catch (InvocationTargetException e) {
|
||||
// Should not happen.
|
||||
Log.w("ApiDemos", "Unable to invoke startForeground", e);
|
||||
Log.e(LOGTAG, "Unable to invoke startForeground", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
// Should not happen.
|
||||
Log.w("ApiDemos", "Unable to invoke startForeground", e);
|
||||
Log.e(LOGTAG, "Unable to invoke startForeground", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -352,11 +369,15 @@ public class WatcherService extends Service
|
||||
try {
|
||||
mSetForegroundArgs[0] = Boolean.TRUE;
|
||||
mSetForeground.invoke(this, mSetForegroundArgs);
|
||||
Log.i(LOGTAG, "setForeground(TRUE) invoked");
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(LOGTAG, "Unable to invoke setForeground", e);
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(LOGTAG, "Unable to invoke setForeground", e);
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
Log.e(LOGTAG, "Unable to invoke setForeground", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -373,12 +394,13 @@ public class WatcherService extends Service
|
||||
mStopForegroundArgs[0] = Boolean.TRUE;
|
||||
try {
|
||||
mStopForeground.invoke(this, mStopForegroundArgs);
|
||||
Log.i(LOGTAG, "stopForeground invoked");
|
||||
} catch (InvocationTargetException e) {
|
||||
// Should not happen.
|
||||
Log.w("ApiDemos", "Unable to invoke stopForeground", e);
|
||||
Log.e(LOGTAG, "Unable to invoke stopForeground", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
// Should not happen.
|
||||
Log.w("ApiDemos", "Unable to invoke stopForeground", e);
|
||||
Log.e(LOGTAG, "Unable to invoke stopForeground", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -390,11 +412,15 @@ public class WatcherService extends Service
|
||||
try {
|
||||
mSetForegroundArgs[0] = Boolean.FALSE;
|
||||
mSetForeground.invoke(this, mSetForegroundArgs);
|
||||
Log.i(LOGTAG, "setForeground(FALSE) invoked");
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(LOGTAG, "Unable to invoke setForeground", e);
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(LOGTAG, "Unable to invoke setForeground", e);
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
Log.e(LOGTAG, "Unable to invoke setForeground", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -402,20 +428,21 @@ public class WatcherService extends Service
|
||||
|
||||
public void doToast(String sMsg)
|
||||
{
|
||||
Log.i("Watcher", sMsg);
|
||||
Log.i(LOGTAG, sMsg);
|
||||
Toast toast = Toast.makeText(this, sMsg, Toast.LENGTH_LONG);
|
||||
toast.setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL, 0, 100);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
public void CheckMem() {
|
||||
System.gc();
|
||||
public void CheckMem()
|
||||
{
|
||||
System.gc();
|
||||
long lFreeMemory = Runtime.getRuntime().freeMemory();
|
||||
long lTotMemory = Runtime.getRuntime().totalMemory();
|
||||
long lMaxMemory = Runtime.getRuntime().maxMemory();
|
||||
|
||||
SendNotification("Memory Check", "Free: " + lFreeMemory + "Total: " + lTotMemory + "Max: " + lMaxMemory);
|
||||
}
|
||||
Log.i(LOGTAG, "Free: " + lFreeMemory + "Total: " + lTotMemory + "Max: " + lMaxMemory);
|
||||
}
|
||||
|
||||
public int UpdtApp(String sPkgName, String sPkgFileName, String sOutFile, int bReboot)
|
||||
{
|
||||
@ -423,45 +450,43 @@ public class WatcherService extends Service
|
||||
int lcv = 0;
|
||||
String sRet = "";
|
||||
|
||||
// Debug.waitForDebugger();
|
||||
|
||||
FileOutputStream f = null;
|
||||
|
||||
try {
|
||||
SendNotification("Killing " + sPkgName, "Step 1: Kill " + sPkgName + " if running");
|
||||
try {
|
||||
Log.i(LOGTAG, "Step 1: Kill " + sPkgName + " if running");
|
||||
while (!IsProcessDead(sPkgName) && (lcv < 5)) {
|
||||
if (KillProcess(sPkgName, null).startsWith("Successfully"))
|
||||
break;
|
||||
else
|
||||
lcv++;
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
|
||||
CheckMem();
|
||||
CheckMem();
|
||||
|
||||
if ((sOutFile != null) && (sOutFile.length() > 0)) {
|
||||
File outFile = new File(sOutFile);
|
||||
if (outFile.exists() && outFile.canWrite()) {
|
||||
f = new FileOutputStream(outFile, true);
|
||||
} else {
|
||||
SendNotification("File not found or cannot write to " + sOutFile, "File not found or cannot write to " + sOutFile);
|
||||
Log.e(LOGTAG, "File not found or cannot write to " + sOutFile);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
e.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
SendNotification("File not found " + sOutFile, "Couldn't open " + sOutFile + " " + e.getLocalizedMessage());
|
||||
Log.e(LOGTAG, "Couldn't open " + sOutFile + " " + e.getLocalizedMessage());
|
||||
e.printStackTrace();
|
||||
} catch (SecurityException e) {
|
||||
SendNotification("Security excepetion for " + sOutFile, "Exception message " + e.getLocalizedMessage());
|
||||
} catch (SecurityException e) {
|
||||
Log.e(LOGTAG, "Exception message " + e.getLocalizedMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if ((sPkgName != null) && (sPkgName.length() > 0))
|
||||
{
|
||||
SendNotification("Uninstalling " + sPkgName, "Step 2: Uninstall " + sPkgName);
|
||||
Log.i(LOGTAG, "Step 2: Uninstall " + sPkgName);
|
||||
sRet = UnInstallApp(sPkgName, null);
|
||||
CheckMem();
|
||||
CheckMem();
|
||||
if ((sRet.length() > 0) && (f != null))
|
||||
{
|
||||
try {
|
||||
@ -477,10 +502,10 @@ public class WatcherService extends Service
|
||||
|
||||
if ((sPkgFileName != null) && (sPkgFileName.length() > 0))
|
||||
{
|
||||
SendNotification("Installing " + sPkgFileName, "Step 3: Install " + sPkgFileName);
|
||||
Log.i(LOGTAG, "Step 3: Install " + sPkgFileName);
|
||||
sRet = InstallApp(sPkgFileName, null);
|
||||
SendNotification("Installed " + sPkgFileName, "" + sRet);
|
||||
CheckMem();
|
||||
Log.i(LOGTAG, "" + sRet);
|
||||
CheckMem();
|
||||
if ((sRet.length() > 0) && (f != null))
|
||||
{
|
||||
try {
|
||||
@ -533,7 +558,7 @@ public class WatcherService extends Service
|
||||
theArgs[0] = "su";
|
||||
theArgs[1] = "-c";
|
||||
theArgs[2] = "reboot";
|
||||
Log.i("Watcher", "Running reboot!");
|
||||
Log.i(LOGTAG, "Running reboot!");
|
||||
|
||||
try
|
||||
{
|
||||
@ -568,7 +593,7 @@ public class WatcherService extends Service
|
||||
List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses();
|
||||
int lcv = 0;
|
||||
String strProcName = "";
|
||||
int nPID = 0;
|
||||
int nPID = 0;
|
||||
int nProcs = 0;
|
||||
|
||||
if (lProcesses != null)
|
||||
@ -698,22 +723,6 @@ public class WatcherService extends Service
|
||||
return(sRet);
|
||||
}
|
||||
|
||||
public String GetTmpDir()
|
||||
{
|
||||
String sRet = "";
|
||||
Context ctx = getApplicationContext();
|
||||
File dir = ctx.getFilesDir();
|
||||
ctx = null;
|
||||
try {
|
||||
sRet = dir.getCanonicalPath();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return(sRet);
|
||||
}
|
||||
|
||||
public String UnInstallApp(String sApp, OutputStream out)
|
||||
{
|
||||
String sRet = "";
|
||||
@ -782,11 +791,11 @@ public class WatcherService extends Service
|
||||
|
||||
private String SendPing(String sIPAddr)
|
||||
{
|
||||
Process pProc;
|
||||
Process pProc;
|
||||
String sRet = "";
|
||||
String [] theArgs = new String [4];
|
||||
boolean bStillRunning = true;
|
||||
int nBytesOut = 0;
|
||||
int nBytesOut = 0;
|
||||
int nBytesErr = 0;
|
||||
int nBytesRead = 0;
|
||||
byte[] buffer = new byte[1024];
|
||||
@ -795,7 +804,7 @@ public class WatcherService extends Service
|
||||
theArgs[1] = "-c";
|
||||
theArgs[2] = "3";
|
||||
theArgs[3] = sIPAddr;
|
||||
Log.i("Watcher", "Pinging " + sIPAddr);
|
||||
Log.i(LOGTAG, "Pinging " + sIPAddr);
|
||||
|
||||
try
|
||||
{
|
||||
@ -872,7 +881,7 @@ public class WatcherService extends Service
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Log.i("Watcher", String.format("Ping result was: '%s'", sRet.trim()));
|
||||
Log.i(LOGTAG, String.format("Ping result was: '%s'", sRet.trim()));
|
||||
return (sRet);
|
||||
}
|
||||
|
||||
@ -903,7 +912,7 @@ public class WatcherService extends Service
|
||||
String msPkgName = "";
|
||||
String msPkgFileName = "";
|
||||
String msOutFile = "";
|
||||
int mbReboot = 0;
|
||||
int mbReboot = 0;
|
||||
|
||||
public UpdateApplication(String sPkgName, String sPkgFileName, String sOutFile, int bReboot) {
|
||||
runner = new Thread(this);
|
||||
@ -915,9 +924,9 @@ public class WatcherService extends Service
|
||||
}
|
||||
|
||||
public void run() {
|
||||
bInstalling = true;
|
||||
bInstalling = true;
|
||||
UpdtApp(msPkgName, msPkgFileName, msOutFile, mbReboot);
|
||||
bInstalling = false;
|
||||
bInstalling = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -944,11 +953,11 @@ public class WatcherService extends Service
|
||||
String sRet = SendPing(sPingTarget);
|
||||
if (!sRet.contains("3 received"))
|
||||
{
|
||||
Log.i("Watcher", String.format("Failed ping attempt (remaining: %s)!",
|
||||
nMaxStrikes - nStrikes));
|
||||
Log.i(LOGTAG, String.format("Failed ping attempt (remaining: %s)!",
|
||||
nMaxStrikes - nStrikes));
|
||||
if (++nStrikes >= nMaxStrikes)
|
||||
{
|
||||
Log.e("Watcher", String.format("Number of failed ping attempts to %s (%s) exceeded maximum (%s), running reboot!", sPingTarget, nStrikes, nMaxStrikes));
|
||||
Log.e(LOGTAG, String.format("Number of failed ping attempts to %s (%s) exceeded maximum (%s), running reboot!", sPingTarget, nStrikes, nMaxStrikes));
|
||||
RunReboot(null);
|
||||
}
|
||||
}
|
||||
@ -960,18 +969,16 @@ public class WatcherService extends Service
|
||||
|
||||
String sProgramName = "com.mozilla.SUTAgentAndroid";
|
||||
|
||||
// Debug.waitForDebugger();
|
||||
|
||||
// Ensure the sdcard is mounted before we even attempt to start the agent
|
||||
// We will wait for the sdcard to mount for PERIODS_TO_WAIT_FOR_SDCARD
|
||||
// after which time we go ahead and attempt to start the agent.
|
||||
if (nPeriodsWaited++ < PERIODS_TO_WAIT_FOR_SDCARD) {
|
||||
String state = Environment.getExternalStorageState();
|
||||
if (Environment.MEDIA_MOUNTED.compareTo(state) != 0) {
|
||||
Log.i("SUTAgentWatcher", "SDcard not mounted, waiting another turn");
|
||||
Log.i(LOGTAG, "SDcard not mounted, waiting another turn");
|
||||
return;
|
||||
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
|
||||
Log.e("SUTAgentWatcher", "SDcard mounted read only not starting agent now, try again in 60s");
|
||||
Log.e(LOGTAG, "SDcard mounted read only not starting agent now, try again in 60s");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -979,7 +986,7 @@ public class WatcherService extends Service
|
||||
boolean isProc = GetProcessInfo(sProgramName);
|
||||
if (bStartSUTAgent && !isProc)
|
||||
{
|
||||
Log.i("SUTAgentWatcher", "Starting SUTAgent from watcher code");
|
||||
Log.i(LOGTAG, "Starting SUTAgent from watcher code");
|
||||
Intent agentIntent = new Intent();
|
||||
agentIntent.setPackage(sProgramName);
|
||||
agentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@ -1013,14 +1020,4 @@ public class WatcherService extends Service
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendNotification(String tickerText, String expandedText) {
|
||||
Log.i("Watcher", expandedText);
|
||||
}
|
||||
|
||||
private void CancelNotification() {
|
||||
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user