Im trying to make a service that would provide data of usagestat every x second. However i always getting the same value after x second. I already clear the map to include new data set from usagemanager. below is my service class thank you in advance.
I do know that in order to retrieve queries every x time, we may use queryevent. However, the total time in foreground for this fit my project, and i already tested using the code for adapter. In the adapter, it do retrieve usage time, however it only provide new value on restarting the activity where the adapter used.
public class PushService extends Service {
private static final int NOTIF_ID = 1;
private static final String NOTIF_CHANNEL_ID = "Channel_Id_1";
private static final String NOTIF_CHANNEL_ID2 = "Channel_Id_2";
private static final int _DISPLAY_ORDER_USAGE_TIME = 0;
private static final int _DISPLAY_ORDER_LAST_TIME_USED = 1;
private static final int _DISPLAY_ORDER_APP_NAME = 2;
private static final boolean localLOGV = false;
private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME;
private AppNameComparator mAppLabelComparator;
private LastTimeUsedComparator mLastTimeUsedComparator;
private UsageTimeComparator mUsageTimeComparator;
private PackageManager mPm;
private UsageStatsManager mUsageStatsManager;
public HashMap<String, Long> mapToFirebase = new HashMap<>();;
public ArrayList<UsageStats> mPackageStats;
public ArrayMap<String, String> mAppLabelMap;
public List<UsageStats> stats;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
/*notice*/
startForeground();
if (intent != null){
String uid = intent.getStringExtra("parentUID");
if (!uid.equals("")){
Toast.makeText(this, uid, Toast.LENGTH_SHORT).show();
Handler ha=new Handler();
ha.postDelayed(new Runnable() {
#Override
public void run() {
//call function
pushAppList();
mapToFirebase.clear();
loadDataToMapForFirebase();
Log.d("mapservice", mapToFirebase.toString());
ha.postDelayed(this, 5000);
}
}, 10000);
}
}
return super.onStartCommand(intent, flags, startId);
}
public static class AppNameComparator implements Comparator<UsageStats> {
private Map<String, String> mAppLabelList;
AppNameComparator(Map<String, String> appList) {
mAppLabelList = appList;
}
#Override
public final int compare(UsageStats a, UsageStats b) {
String alabel = mAppLabelList.get(a.getPackageName());
String blabel = mAppLabelList.get(b.getPackageName());
return alabel.compareTo(blabel);
}
}
public void pushAppList(){
mAppLabelMap = new ArrayMap<>();
mPackageStats = new ArrayList<>();
mPm = getPackageManager();
mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, -5);
mLastTimeUsedComparator = new LastTimeUsedComparator();
mUsageTimeComparator = new UsageTimeComparator();
stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, cal.getTimeInMillis(), System.currentTimeMillis());
if (stats == null) {
return;
}
ArrayMap<String, UsageStats> map = new ArrayMap<>();
int statCount = stats.size();
for (int i = 0; i < statCount; i++) {
Log.d("", String.valueOf(stats.get(i).getTotalTimeInForeground()));
android.app.usage.UsageStats pkgStats = stats.get(i);
// load application labels for each application
try {
ApplicationInfo appInfo = mPm.getApplicationInfo(pkgStats.getPackageName(), 0);
String label = appInfo.loadLabel(mPm).toString();
mAppLabelMap.put(pkgStats.getPackageName(), label);
UsageStats existingStats =
map.get(pkgStats.getPackageName());
if (existingStats == null) {
map.put(pkgStats.getPackageName(), pkgStats);
} else {
existingStats.add(pkgStats);
}
} catch (PackageManager.NameNotFoundException e) {
// This package may be gone.
}
}
mPackageStats.addAll(map.values());
// Sort list
mAppLabelComparator = new AppNameComparator(mAppLabelMap);
sortList();
}
public static class LastTimeUsedComparator implements Comparator<UsageStats> {
#Override
public final int compare(UsageStats a, UsageStats b) {
// return by descending order
return (int)(b.getLastTimeUsed() - a.getLastTimeUsed());
}
}
public static class UsageTimeComparator implements Comparator<UsageStats> {
#Override
public final int compare(UsageStats a, UsageStats b) {
return (int)(b.getTotalTimeInForeground() - a.getTotalTimeInForeground());
}
}
private void sortList() {
if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) {
if (localLOGV) Log.i(TAG, "Sorting by usage time");
Collections.sort(mPackageStats, mUsageTimeComparator);
} else if (mDisplayOrder == _DISPLAY_ORDER_LAST_TIME_USED) {
if (localLOGV) Log.i(TAG, "Sorting by last time used");
Collections.sort(mPackageStats, mLastTimeUsedComparator);
} else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) {
if (localLOGV) Log.i(TAG, "Sorting by application name");
Collections.sort(mPackageStats, mAppLabelComparator);
}
}
public void loadDataToMapForFirebase(){
/*TODO UPDATE DATA ONBACKGROUND*/
String system_sign = "android";
PackageManager pm = getPackageManager();
if (mPackageStats.size() != 0){
for (int i = 0; i < mPackageStats.size(); i++){
if (pm.checkSignatures(system_sign, mPackageStats.get(i).getPackageName()) == PackageManager.SIGNATURE_MATCH) {
Log.d("CheckAppSys", mPackageStats.get(i).getPackageName() + " is sys.");
} else {
String usagetime = DateUtils.formatElapsedTime(mPackageStats.get(i).getTotalTimeInForeground() / 1000);
Pattern special= Pattern.compile("[^a-z0-9 ]", Pattern.CASE_INSENSITIVE);
Matcher matcher = special.matcher(Objects.requireNonNull(mAppLabelMap.get(mPackageStats.get(i).getPackageName())));
boolean constainsSymbols = matcher.find();
if(!constainsSymbols){
mapToFirebase.put(mAppLabelMap.get(mPackageStats.get(i).getPackageName()), mPackageStats.get(i).getTotalTimeInForeground());
}
Log.d("maptofirebase", mapToFirebase.toString());
Log.d("CheckApp", mPackageStats.get(i).getPackageName() + " is not sys.");
}
}
}
}
private void startForeground() {
Intent notificationIntent = new Intent(this, UsageStatsActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel1 = new NotificationChannel(
NOTIF_CHANNEL_ID,
"Channel 1",
NotificationManager.IMPORTANCE_HIGH
);
channel1.setDescription("This is channel 1");
NotificationChannel channel2 = new NotificationChannel(
NOTIF_CHANNEL_ID2,
"Channel 2",
NotificationManager.IMPORTANCE_LOW
);
channel2.setDescription("This is channel 2");
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel1);
manager.createNotificationChannel(channel2);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
startForeground(NOTIF_ID, new NotificationCompat.Builder(this,
NOTIF_CHANNEL_ID) // don't forget create a notification channel first
.setOngoing(true)
.setSmallIcon(R.drawable.logo)
.setContentTitle(getString(R.string.app_name))
.setContentText("Monitoring apps.")
.setContentIntent(pendingIntent)
.build());
}
}
Related
I have to do an android service that communicates with a web service within 45 seconds. but i can't do it with business service or normal service. The system automatically shuts itself down after 10 minutes. I need help.
public class bildirim extends JobService {
int Kul_Id = 0;
String[] sto;
int sayac = 0;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public boolean onStartJob(JobParameters params) {
final ipdatabase dbo = new ipdatabase(getBaseContext());
sto = dbo.ipler(getBaseContext());
database db = new database(bildirim.this);
if (db.dbkontrol()) {
List<String> cr = db.veriListele(2);
if (!cr.isEmpty()) {
Kul_Id = Integer.parseInt(cr.get(4));
}
}
Timer tmr = new Timer();
tmr.schedule(new TimerTask() {
#Override
public void run() {
new arkaplan().execute("http://" + sto[0] + "/Services.asmx/bildirimal?Kul_ID=" + Kul_Id+"&durum=1");
}
},0,30000);
return false;
}
#Override
public boolean onStopJob(JobParameters params) {
return false;
}
#Override
public void onDestroy() {
JobSchedulerService.scheduleJob(getApplicationContext());
super.onDestroy();
}
class arkaplan extends AsyncTask<String, String, String> {
protected String doInBackground(String... params) {
return jsonparser.getdata(params[0]);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
JSONObject obj = new JSONObject(s);
JSONArray listarray = obj.getJSONArray("list");
JSONObject fistobj;
for (int i = 0; i < listarray.length(); i++) {
fistobj = listarray.getJSONObject(i);
int icon = R.drawable.redwhitefav;
NotificationManagerCompat notifiynm = NotificationManagerCompat.from(bildirim.this);
Notification notifiy = new NotificationCompat.Builder(bildirim.this, CHANNEL_1_ID)
.setSmallIcon(icon)
.setContentTitle(fistobj.getString("Gork_Deger") + ": " + fistobj.getString("Gork_Mstad"))
.setContentText("Tanım: "+ fistobj.getString("Gork_Tanim") + "\n"+ "Tarih: " + fistobj.getString("Gork_Baslangic"))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_REMINDER)
.build();
notifiynm.notify(sayac, notifiy);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
I'm trying to start a service that adds an item to RecyclerView every 24 hours (every day). I used this code but it doesn't work:
BackgroundService.java
public class BackgroundService extends Service {
private boolean isRunning;
private Context context;
private Thread backgroundThread;
SharedPreferences pref;
String isMorningChecked;
String isEveningChecked;
String isNightChecked;
String isEchuraistChecked;
String isConfessChecked;
String isBibleChecked;
String Date;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
this.context = this;
this.isRunning = false;
this.backgroundThread = new Thread(addNewNote);
}
private Runnable addNewNote = new Runnable() {
#Override
public void run() {
Log.e("isRunning", "Yeeeeeeeeeees!");
pref = getApplicationContext().getSharedPreferences("checkStates", 0);
String checkMorningState = pref.getString("morning", "False");
String checkEveningState = pref.getString("evening", "False");
String checkNightState = pref.getString("night", "False");
String checkEchuraistState = pref.getString("echuraist", "False");
String checkConfessState = pref.getString("confess", "False");
String checkBibleState = pref.getString("bible", "False");
String writeYourNotes = pref.getString("writeNotes", "");
SimpleDateFormat sdf = new SimpleDateFormat("E", new Locale("ar"));
final SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy.MM.dd");
final Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Date = sdf2.format(timestamp).toString();
if(checkMorningState.equals("True")){
isMorningChecked = "+";
}else{
isMorningChecked = "-";
}
if(checkEveningState.equals("True")){
isEveningChecked = "+";
}else{
isEveningChecked = "-";
}
if(checkNightState.equals("True")){
isNightChecked = "+";
}else{
isNightChecked = "-";
}
if(checkEchuraistState.equals("True")){
isEchuraistChecked = "+";
}else{
isEchuraistChecked = "-";
}
if(checkConfessState.equals("True")){
isConfessChecked = "+";
}else{
isConfessChecked = "-";
}
if(checkBibleState.equals("True")){
isBibleChecked = "+";
}else{
isBibleChecked = "-";
}
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "Note").allowMainThreadQueries().build();
db.userDao().insertAll(new Note(sdf.format(timestamp), sdf2.format(timestamp).toString(), isMorningChecked, isEveningChecked, isNightChecked, isEchuraistChecked, isConfessChecked, isBibleChecked, writeYourNotes));
stopSelf();
}
};
#Override
public void onDestroy() {
super.onDestroy();
this.isRunning = false;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(!this.isRunning){
this.isRunning = true;
this.backgroundThread.start();
}
return START_STICKY;
}
}
BoardCastReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, BackgroundService.class));
}
}
Home.java
Intent alarm = new Intent(this, AlarmReceiver.class);
boolean alarmRunning = ((PendingIntent.getBroadcast(this,0,alarm,PendingIntent.FLAG_NO_CREATE)) != null);
if(alarmRunning == false){
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,alarm,0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 1000, pendingIntent);
I have tried this but the Service works once or twice and then it stops and sometimes it gives me the following error:
java.lang.IllegalStateException: Not allowed to start service Intent
Background service can not be used for long running tasks on Android 8.0 onwards. Please use JobScheduler API or Workmanager to achieve the desired results. Consult the following link for details.
https://developer.android.com/topic/libraries/architecture/workmanager
I want to use alarm based on some database time value . Currently my alarm is working for one alarm Like : I have 3 alarm set at 8:30am , 10:20am and 12:20Pm
my alarm is working only for one value .This is reminder class there i am creating the alarm
public class OwnGoalReminder extends EventReminder {
GoalOwn goalOwn;
int interValTime;
int goalId;
int hour;
int minute;
int requestCode;
String type;
public void setInterValTime(int interValTime) {
this.interValTime = interValTime;
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public void setRequestCode(int requestCode) {
this.requestCode = requestCode;
}
public void setType(String type) {
this.type = type;
}
public int getMinute() {
return minute;
}
#Override
protected int getGoalId(){return this.goalId;}
public void setMinute(int minute) {
this.minute = minute;
}
public OwnGoalReminder(Context context , int goalId, int interValTime){
super(context);
this.interValTime = interValTime;
this.goalId = goalId;
}
#Override
protected String getType() {
return this.type;
}
#Override
protected String getMessage() {
return "Reminder!!! You should check your goals!";
}
#Override
protected int getRequestCode() {
return requestCode;
}
#Override
protected EventTime getEventTime() {
int h = hour;
int m = minute;
return new EventTime(hour,minute,interValTime);
}
#Override
protected Class getBroadcastReceiver() {
return MyBroadcastReceiver.class;
}
}
This is base class of OwnGOalReminder
public abstract class EventReminder{
protected Context context;
protected Alarm alarm;
PushNotificationsManager notificationsManager;
public void remind() {
Bundle bundle = new Bundle();
bundle.putString("type", getType());
bundle.putString("msg", getMessage());
notificationsManager.sendNotification(bundle);
}
protected abstract String getType();
protected abstract String getMessage();
protected abstract int getRequestCode();
protected abstract int getGoalId();
protected abstract EventTime getEventTime();
protected abstract Class getBroadcastReceiver();
protected EventReminder(Context context){
this.context = context;
alarm = new Alarm(context, getBroadcastReceiver());
notificationsManager = new PushNotificationsManager(context);
}
public void startReminder(){
alarm.startAlert(getRequestCode(), getGoalId(), getEventTime().hour, getEventTime().minute, getEventTime().intervalInMinute);
//alarm.setAlarm(context, getEventTime().hour, getEventTime().minute);
}
protected class EventTime{
int hour, minute, intervalInMinute;
public EventTime(int hour, int minute, int intervalInMinute){
this.hour = hour;
this.minute = minute;
this.intervalInMinute = intervalInMinute;
}
}
}
this is alarm class there i am creating the alarmmanager
public class Alarm{
private final Context context;
private Class broadcastReceiver;
public Alarm(Context context, Class broadcastReceiver){
this.context = context;
this.broadcastReceiver = broadcastReceiver;
}
public void startAlert(int requestCode, int gid, int hour, int minute, int intervalMinute) {
Log.d(this.getClass().getName(), "starting alert");
int i = 10;
Long timeToMilliSeconds = timeToMilliSeconds(hour, minute);
Intent intent = new Intent(context, MyBroadcastReceiver.class);
intent.putExtra("reqcode", requestCode);
intent.putExtra("time", timeToMilliSeconds);
intent.putExtra("gid" , gid);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, timeToMilliSeconds+
+ (i * 1000), 1000*60*intervalMinute, pendingIntent);
//Toast.makeText(context, "Alarm set in " + i + " seconds",Toast.LENGTH_LONG).show();
}
#NonNull
public static long timeToMilliSeconds(int hour, int minute) {
Date dat = new Date();//initializes to now
Calendar cal_alarm = Calendar.getInstance();
Calendar cal_now = Calendar.getInstance();
cal_now.setTime(dat);
cal_alarm.setTime(dat);
cal_alarm.set(Calendar.HOUR_OF_DAY,hour);//set the alarm time
cal_alarm.set(Calendar.MINUTE, minute);
cal_alarm.set(Calendar.SECOND,0);
if(cal_alarm.getTimeInMillis() < System.currentTimeMillis()){
cal_alarm.add(Calendar.DAY_OF_YEAR,1);
}
return cal_alarm.getTimeInMillis();
}
}
This is the method here i am creating the multiple alarm object based on database value
public static void registerAlarm(Context context){
if(!UserPreferences.isAlarmRegistered(context)) {
GoalReminder goalReminder = new GoalReminder(context);
AppraisalReminder appraisalReminder = new AppraisalReminder(context);
goalReminder.startReminder();
appraisalReminder.startReminder();
// ownGoalReminder.startReminder();
//UserPreferences.setIsAlarmRegistered(context,true);
ArrayList<Goal> LIST_OF_OWN_GOALS = new ArrayList<>();
LIST_OF_OWN_GOALS = (ArrayList<Goal>) Goal.getGoalFromOwnGoals();
for (Goal g : LIST_OF_OWN_GOALS) {
OwnGoalReminder ownGoalReminder = new OwnGoalReminder(context , g.getgId(),3 );
int h = Integer.parseInt(g.getrTime())/60;
int min = Integer.parseInt(g.getrTime())%60;
ownGoalReminder.setHour(h);
ownGoalReminder.setMinute(min);
ownGoalReminder.setRequestCode(16);
ownGoalReminder.setType("16");
ownGoalReminder.startReminder();
LIST_OF_OWN_REMINDERS.add(ownGoalReminder);
}
}
}
This is my Broadcast receiver class :
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String[] goalMessagesArray = ApraiseApplication.getContext().getResources().getStringArray(R.array.goals_messages);
private static Queue<String> goalMessagesQueue = new ArrayDeque<>(Arrays.asList(goalMessagesArray));
private static final String[] appraisalsMessagesArray = ApraiseApplication.getContext().getResources().getStringArray(R.array.appraisals_messages);
private static Queue<String> appraisalsMessagesQueue = new ArrayDeque<>(Arrays.asList(appraisalsMessagesArray));
#Override
public void onReceive(Context context, Intent intent) {
Log.d(this.getClass().getName(), "notify");
PushNotificationsManager notificationsManager = new PushNotificationsManager(context);
PowerManager.WakeLock wl = acquireWakeLock(context);
int requestCode = intent.getIntExtra("reqcode",1);
int gId = intent.getIntExtra("gid",1);
long time = intent.getLongExtra("time",0);
String message = "";
// it will create the instance of Random class
Random randomGenerator = new Random();
// it will generate a random number based on goal message arrayList length
int indexForGoalMessage = randomGenerator.nextInt(goalMessagesArray.length);
// it will generate a random number based on appraisalsMessagesArray length
int indexForAppraisalsMessage = randomGenerator.nextInt(goalMessagesArray.length);
String gid = "";
if(isNotifyTimePassed(time)){
//return;
}
if(requestCode == 123){
// if(goalMessagesQueue.isEmpty()){
// goalMessagesQueue = new ArrayDeque<>(Arrays.asList(goalMessagesArray));
// }
// message = goalMessagesQueue.poll();
message = goalMessagesArray[indexForGoalMessage];
}else if(requestCode == 124){
// if(appraisalsMessagesQueue.isEmpty()){
// appraisalsMessagesQueue = new ArrayDeque<>(Arrays.asList(appraisalsMessagesArray));
// }
// message = appraisalsMessagesQueue.poll();
message = appraisalsMessagesArray[indexForAppraisalsMessage];
}
Bundle bundle = new Bundle();
bundle.putString("type", Integer.toString(requestCode));
bundle.putString("msg", message);
bundle.putString("gid" , String.valueOf(gId));
notificationsManager.sendNotification(bundle);
wl.release();
}
#NonNull
private PowerManager.WakeLock acquireWakeLock(Context context) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
return wl;
}
private boolean isNotifyTimePassed(long time) {
return (System.currentTimeMillis()-time) > 1000L*60L*5L;
}
}
[I have found this solution from searching google ]
I have solved that problem by passing unique id which is depend on current time:-
final int intent_id= (int) System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, intent_id , intent, PendingIntent.FLAG_UPDATE_CURRENT);
It is good to set your event id (unique id) as the request code of PendingIntent.getBroadcast() method. So the advantage here is when you update/edit the event then alarm wont duplicate.
I have an activity that calls a service on its onCreate , however when I try yo run the project I keep getting an error saying the service has leaked and longer bound on the activity that called/registered it .
"Activity com.xera.deviceinsight.home.DataUsageActivity has leaked ServiceConnection com.xera.deviceinsight.home.DataUsageActivity$3#42676a48 that was originally bound here" I am assuming this might have something to do with the lifecycle of the activity . I have both the activity and the service in question below
myActivity
public class DataUsageActivity extends AppCompatActivity implements MonitorService.ServiceCallback
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TinyDB settings = new TinyDB(this);
if (settings.getBoolean(AppPreferences.HAS_LOGGED_IN))
{
this.bindService(
new Intent(this, MonitorService.class),
serviceConnection,
Context.BIND_AUTO_CREATE);
return;
}
}
public void sendResults(int resultCode, Bundle b)
{
// adapter.notifyDataSetChanged();
}
private ServiceConnection serviceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName className, IBinder service)
{
MonitorService.LocalBinder binder = (MonitorService.LocalBinder)service;
backgroundService = binder.getService();
backgroundService.setCallback(DataUsageActivity.this);
backgroundService.start();
}
#Override
public void onServiceDisconnected(ComponentName className)
{
backgroundService = null;
}
};
#Override
public void onResume()
{
super.onResume();
if(backgroundService != null)
{
backgroundService.setCallback(this);
}
}
#Override
public void onPause()
{
super.onPause();
if(backgroundService != null)
{
backgroundService.setCallback(null);
}
}
}
**myService**
public class MonitorService extends Service
{
private boolean initialized = false;
private final IBinder mBinder = new LocalBinder();
private ServiceCallback callback = null;
private Timer timer = null;
private final Handler mHandler = new Handler();
private String foreground = null;
private ArrayList<HashMap<String,Object>> processList;
private ArrayList<String> packages;
private Date split = null;
// private Date startTime = null;
public int timeCheckVariable = 0 ;
public static int SERVICE_PERIOD = 5000; // TODO: customize (this is for scan every 5 seconds)
private final ProcessList pl = new ProcessList(this)
{
#Override
protected boolean isFilteredByName(String pack)
{
// TODO: filter processes by names, return true to skip the process
// always return false (by default) to monitor all processes
return false;
}
};
public interface ServiceCallback
{
void sendResults(int resultCode, Bundle b);
}
public class LocalBinder extends Binder
{
MonitorService getService()
{
// Return this instance of the service so clients can call public methods
return MonitorService.this;
}
}
#Override
public void onCreate()
{
super.onCreate();
initialized = true;
processList = ((DeviceInsightApp)getApplication()).getProcessList();
packages = ((DeviceInsightApp)getApplication()).getPackages();
}
#Override
public IBinder onBind(Intent intent)
{
if(initialized)
{
return mBinder;
}
return null;
}
public void setCallback(ServiceCallback callback)
{
this.callback = callback;
}
// private boolean addToStatistics(String target , Long startTime)
private boolean addToStatistics(String target )
{
boolean changed = false;
Date now = new Date();
if(!TextUtils.isEmpty(target))
{
if(!target.equals(foreground))
{
int i;
// timeCheckVariable = i ;
if(foreground != null && split != null)
{
// TODO: calculate time difference from current moment
// to the moment when previous foreground process was activated
i = packages.indexOf(foreground);
timeCheckVariable = i ;
long delta = (now.getTime() - split.getTime()) / 1000;
Long time = (Long)processList.get(i).get(ProcessList.COLUMN_PROCESS_TIME);
if(time != null)
{
// TODO: add the delta to statistics of 'foreground'
time += delta;
}
else
{
time = new Long(delta);
}
processList.get(i).put(ProcessList.COLUMN_PROCESS_TIME, time);
//String applicationName = (String)processList.get(i).get(ProcessList.COLUMN_PROCESS_NAME);
// DatabaseHandler db = new DatabaseHandler(this);
// int x = time.intValue( );
// db.addAppRecord(new AppUsageClass(applicationName , x));
// db.getApplicationCount();
// List<AppUsageClass> appUsageClass = db.getAllApplications();
// db.getApplicationCount();
// for (AppUsageClass cn : appUsageClass) {
//String log = "Id: " + cn.getID() + " ,ApplicationName : " + cn.getName() + " ,TimeSpent: " + cn.getTimeSpent();
// Log.d("Name: ", log);
//}
}
//update count of process activation for new 'target'
i = packages.indexOf(target);
Integer count = (Integer)processList.get(i).get(ProcessList.COLUMN_PROCESS_COUNT);
if(count != null) count++;
else
{
count = new Integer(1);
}
processList.get(i).put(ProcessList.COLUMN_PROCESS_COUNT, count);
foreground = target;
split = now;
changed = true;
}
}
//Long checkTimeNow = (Long)processList.get(timeCheckVariable).get(ProcessList.COLUMN_PROCESS_TIME);
return changed;
}
public void start()
{
if(timer == null)
{
timer = new Timer();
timer.schedule(new MonitoringTimerTask(), 500, SERVICE_PERIOD);
}
// TODO: startForeground(srvcid, createNotification(null));
}
public void stop()
{
timer.cancel();
timer.purge();
timer = null;
}
private class MonitoringTimerTask extends TimerTask
{
#Override
public void run()
{
fillProcessList();
ActivityManager activityManager = (ActivityManager)MonitorService.this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1);
String current = taskInfo.get(0).topActivity.getPackageName(); // gets the application which is in the foreground
int i = packages.indexOf(current);
Long timecheck = (Long)processList.get(i).get(ProcessList.COLUMN_PROCESS_TIME);
if(addToStatistics(current)&& callback != null)
{
final Bundle b = new Bundle();
// TODO: pass necessary info to UI via bundle
mHandler.post(new Runnable()
{
public void run()
{
callback.sendResults(1, b);
}
});
}
}
}
private void fillProcessList()
{
pl.fillProcessList(processList, packages);
}
The problem is that you don't unbind from you service in .onPause() or in .onDestroy(), so if you Activity is destroyed, connection still last, so there is leaked connection. If you want you service to run all the time, you should start it by .startService() and then bind to it. In .onStop() or .onDestroy() unbind from that service
I have a very big problem guys. I have an app which fetches and parses the RSS feed from a blog, but I don't know how to put the results into my widget.
Here is the RSSListActivity which shows the rss feed correctly in it's own activity:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
RSSItem data = itemlist.get(position);
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse(data.link));
startActivity(intent);
}
private void retrieveRSSFeed(String urlToRssFeed,ArrayList<RSSItem> list)
{
try
{
URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RSSParser theRssHandler = new RSSParser(list);
xmlreader.setContentHandler(theRssHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private class RetrieveRSSFeeds extends AsyncTask<Void, Void, Void>
{
private ProgressDialog progress = null;
#Override
protected Void doInBackground(Void... params) {
retrieveRSSFeed("http://blog.qubiz.com/index.php/feed",itemlist);
rssadaptor = new RSSListAdaptor(RSSListActivity.this, R.layout.rssitemview,itemlist);
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
}
#Override
protected void onPreExecute() {
progress = ProgressDialog.show(
RSSListActivity.this, null, "Loading RSS Feed... Please wait");
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
setListAdapter(rssadaptor);
progress.dismiss();
super.onPostExecute(result);
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
private class RSSListAdaptor extends ArrayAdapter<RSSItem>{
private List<RSSItem> objects = null;
public RSSListAdaptor(Context context, int textviewid, List<RSSItem> objects) {
super(context, textviewid, objects);
this.objects = objects;
}
#Override
public int getCount() {
return ((null != objects) ? objects.size() : 0);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public RSSItem getItem(int position) {
return ((null != objects) ? objects.get(position) : null);
}
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(null == view)
{
LayoutInflater vi = (LayoutInflater)RSSListActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.rssitemview, null);
}
RSSItem data = objects.get(position);
if(null != data)
{
TextView title = (TextView)view.findViewById(R.id.txtTitle);
TextView date = (TextView)view.findViewById(R.id.txtDate);
TextView description = (TextView)view.findViewById(R.id.txtDescription);
title.setText(data.title);
date.setText("on " + data.date);
String prova = android.text.Html.fromHtml(data.description).toString();
//description.setText(data.description);
description.setText(prova);
}
return view;
}
}
public boolean onCreateOptionsMenu(Menu menu)
{
menu.add(1,1,0,"About");
return true;
}
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case 1:
AlertDialog.Builder conferma_canc = new AlertDialog.Builder(this);
conferma_canc.setTitle("About");
conferma_canc.setMessage("Copyright © 2012 Qubiz. All rights reserved. Android version designed and developed by Csosz Gergo Levente, Qubiz Romania.");
conferma_canc.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog alert = conferma_canc.create();
alert.show();
return true;
}
return false;
}
And here it is my RSS parser which also works as it should:
public class RSSParser extends DefaultHandler {
private final static String TAG_ITEM = "item";
private final static String[] xmltags = { "title", "link", "pubDate", "description" };
private RSSItem currentitem = null;
private ArrayList<RSSItem> itemarray = null;
private int currentindex = -1;
private boolean isParsing = false;
private StringBuilder builder = new StringBuilder();
public RSSParser(ArrayList<RSSItem> itemarray) {
super();
this.itemarray = itemarray;
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
if(isParsing && -1 != currentindex && null != builder)
{
builder.append(ch,start,length);
}
}
#Override
public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if(localName.equalsIgnoreCase(TAG_ITEM))
{
currentitem = new RSSItem();
currentindex = -1;
isParsing = true;
itemarray.add(currentitem);
}
else
{
currentindex = itemIndexFromString(localName);
builder = null;
if(-1 != currentindex)
builder = new StringBuilder();
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if(localName.equalsIgnoreCase(TAG_ITEM))
{
isParsing = false;
}
else if(currentindex != -1)
{
if(isParsing)
{
switch(currentindex)
{
case 0: currentitem.title = builder.toString(); break;
case 1: currentitem.link = builder.toString(); break;
case 2: currentitem.date = builder.toString(); break;
case 3: currentitem.description= builder.toString(); break;
}
}
}
}
private int itemIndexFromString(String tagname){
int itemindex = -1;
for(int index= 0; index<xmltags.length; ++index)
{
if(tagname.equalsIgnoreCase(xmltags[index]))
{
itemindex = index;
break;
}
}
return itemindex;
}
}
My ExampleAppWidgetProvider.java where is a sample clock widget code which I want to replace to show my rss feed.
public class ExampleAppWidgetProvider extends AppWidgetProvider {
static DateFormat df = new SimpleDateFormat("hh:mm:ss");
private static final String LOG_TAG = "ExampleWidget";
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final int N = appWidgetIds.length;
Log.i("ExampleWidget", "Updating widgets " + Arrays.asList(appWidgetIds));
for (int i = 0; i < N; i++) {
int appWidgetId = appWidgetIds[i];
Intent intent = new Intent(context, ExampleAppWidgetProvider.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget1);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
views.setTextViewText(R.id.widget1label, df.format(new Date()));
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
private PendingIntent createClockTickIntent(Context context) {
Intent intent = new Intent(CLOCK_WIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
Log.d(LOG_TAG, "Widget Provider enabled. Starting timer to update widget every second");
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 1);
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(),1000, createClockTickIntent(context));
}
#Override
public void onDisabled(Context context) {
super.onDisabled(context);
Log.d(LOG_TAG, "Widget Provider disabled. Turning off timer");
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(createClockTickIntent(context));
}
public static String CLOCK_WIDGET_UPDATE = "com.eightbitcloud.example.widget.8BITCLOCK_WIDGET_UPDATE";
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
Log.d(LOG_TAG, "Received intent " + intent);
if (CLOCK_WIDGET_UPDATE.equals(intent.getAction())) {
Log.d(LOG_TAG, "Clock update");
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), getClass().getName());
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
for (int appWidgetID : ids) {updateAppWidget(context, appWidgetManager, appWidgetID);
}
}
}
public static void updateAppWidget(Context context,AppWidgetManager appWidgetManager, int appWidgetId) {
String currentTime = df.format(new Date());
RemoteViews updateViews = new RemoteViews(context.getPackageName(),R.layout.widget1);
updateViews.setTextViewText(R.id.widget1label, currentTime);
appWidgetManager.updateAppWidget(appWidgetId, updateViews);
}
}
Could any1 provide me a solution?
My aim is to: replace the widget's clock java code with my rss feed reader.
So I want to show the last rss item in the widget which is parsed by the rss parser. How can I do that?
Please provide code too, not only a few ideas, I am kinda new to android development.
Thank you for help in advance!
(Assuming you got RSS retrieval and parsing correctly)
You just have to change some text in widget:
AppWidgetManager manager = AppWidgetManager.getInstance(context);
RemoteViews views = new RemoteViews(context.getPackageName(), R.name_of_your_widget_layout);
// set text of some view
views.setTextViewText(R.id.widget_amount_cameras, amountCameras);
// and of another view
views.setTextViewText(R.id.widget_location, locationCity);
// ... and yet another view
views.setTextViewText(R.id.locationStatus, locationStatus);
// get IDs of widgets , there could be more than one
final int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(YOurWidgetProviderClass.class.getPackage().getName(), YOurWidgetProviderClass.class.getName()));
// update all hte instances
manager.updateAppWidget(appWidgetIds, views);
You can change only some attributes of your widgets ( due to security constraints ) - See Javadoc of RemoteViews for further explanations