My app has a widget with two buttons that goes back and forth and displays information stored in a JSONArray. It works very well but the problem is when i close the app the widget stops working because the JSONArray becomes null. How can i keep it working even when the app is closed ?
its too long to post it here but this is the part when i click next button
if(intent.getAction().equals(NEXT_LISTING)){
try{
if (listingNumber !=15)
{
listingNumber++;
}
JSONObject latestListing = jsonListings.getJSONObject(listingNumber);
String titleString = latestListing.getString("title");
String descriptionString = latestListing.getString("description");
String categoryString = latestListing.getString("category");
Date postDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(latestListing.getString("created"));
Date newDate = new Date(postDate.getTime() + Utils.getCurrentTimezoneOffset() * (3600 * 100));
String createdDate = Utils.getFormattedDate(newDate);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.njoftime_widget);
views.setTextViewText(R.id.title, titleString);
views.setTextViewText(R.id.description, descriptionString);
views.setTextViewText(R.id.textView_category, categoryString);
views.setTextViewText(R.id.textView_date, createdDate);
for(int i=0; i < categoriesList.size();i++)
{
if(categoriesList.get(i).get(0).equals(latestListing.getString("category")))
{
views.setImageViewResource(R.id.category_icon_widget, iconList.get(i));
}
}
if(listingThumbnails.get(listingNumber) != null)
{
views.setViewVisibility(R.id.listing_photo, View.VISIBLE);
views.setImageViewUri(R.id.listing_photo, Uri.parse(""));
Bitmap roundedBitmap = getRoundedLeftCornerBitmap(listingThumbnails.get(listingNumber), 10);
views.setImageViewBitmap(R.id.listing_photo,roundedBitmap);
}
else
{
views.setViewVisibility(R.id.listing_photo, View.GONE);
}
// Instruct the widget manager to update the widget
ComponentName componentName = new ComponentName(context, NjoftimeWidget.class);
AppWidgetManager.getInstance(context).updateAppWidget(componentName, views);
}
catch (Exception e)
{
e.printStackTrace();
}
}
Related
I am writing an app that can create Maths worksheet with answer pages in PDF format. I want to add a print function to allow printing the worksheet directly from the app.
In the PrintDocumentAdapter, the first half of the codes check the color of a certain pixel of the page to determine whether it is an answer page and reduce the number of pages to print accordingly. It then constructs a printingPDF document and sends it to print using 's writeTo() method in the onWrite().
Everything works fine until the last part. It reads the PDF correctly, checks the number of answer pages correctly, and sends a correct PDF with question pages only to the printing page. If I choose "Save as PDF" in the printing page, it saves the pages to a new PDF file with no problem. However, if I try to print with my printer that is connected to my phone with USB by clicking the print button, the printing page simply disappears and goes back to the main page of my app. (It is supposed to past those few pages to the printer app.) I tried several different android printer driver apps and the result was the same.
private void printWS() throws IOException {
findViewById(R.id.defaultTextView).setVisibility(View.INVISIBLE);
if (!loadedFile) {
File file = new File(getApplicationContext().getCacheDir(), getString(R.string.defaultFileName));
parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
} else {
parcelFileDescriptor = getContentResolver().openFileDescriptor(pdfUri, "r");
}
// Start printing
PrintManager printManager = (PrintManager) this.getSystemService(PRINT_SERVICE);
String jobName = getString(R.string.app_name);
PrintAttributes printAttributes = new PrintAttributes.Builder().setMediaSize(PrintAttributes.MediaSize.ISO_A4).build();
printManager.print(jobName, new PrintDocumentAdapter() {
int finalTotal;
#Override
public void onStart() {
if (parcelFileDescriptor != null) {
try {
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
} catch (IOException e) {
e.printStackTrace();
}
}
int tempTotal = pdfRenderer.getPageCount();
Bitmap[] tempBitmap = new Bitmap[tempTotal];
finalTotal = tempTotal;
for (int pageNum = 0; pageNum < tempTotal; pageNum++) {
PdfRenderer.Page tempPage = pdfRenderer.openPage(pageNum);
tempBitmap[pageNum] = Bitmap.createBitmap(WS_WIDTH, WS_HEIGHT, Bitmap.Config.ARGB_8888);
tempPage.render(tempBitmap[pageNum], null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
if (tempBitmap[pageNum].getPixel(0, 0) == Color.GRAY) {
finalTotal--;
}
tempPage.close();
}
}
PrintedPdfDocument printingPDF;
#Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle bundle) {
printingPDF = new PrintedPdfDocument(getApplicationContext(), newAttributes);
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
if (finalTotal > 0) {
PrintDocumentInfo info = new PrintDocumentInfo
.Builder("Worksheet")
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(finalTotal)
.build();
callback.onLayoutFinished(info, true);
} else {
callback.onLayoutFailed("Page count calculation failed.");
}
}
#Override
public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) {
Bitmap[] loadedBitmap = new Bitmap[finalTotal];
for (int pageNum = 0; pageNum < finalTotal; pageNum++) {
PdfDocument.PageInfo printingPageInfo = new PdfDocument.PageInfo.Builder(WS_WIDTH, WS_HEIGHT, pageNum).create();
PdfDocument.Page printingPage = printingPDF.startPage(printingPageInfo);
if (cancellationSignal.isCanceled()) {
callback.onWriteCancelled();
printingPDF.close();
printingPDF = null;
return;
}
PdfRenderer.Page loadedPage = pdfRenderer.openPage(pageNum);
loadedBitmap[pageNum] = Bitmap.createBitmap(WS_WIDTH, WS_HEIGHT, Bitmap.Config.ARGB_8888);
loadedPage.render(loadedBitmap[pageNum], null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
Canvas canvas = printingPage.getCanvas();
Paint paint = new Paint();
canvas.drawBitmap(loadedBitmap[pageNum], 0, 0, paint);
printingPDF.finishPage(printingPage);
loadedPage.close();
}
try {
printingPDF.writeTo(new FileOutputStream(destination.getFileDescriptor()));
} catch (IOException e) {
callback.onWriteFailed(e.toString());
return;
} finally {
printingPDF.close();
printingPDF = null;
}
PageRange[] writtenPages = new PageRange[]{PageRange.ALL_PAGES};
callback.onWriteFinished(writtenPages);
}
#Override
public void onFinish() {
try {
pdfRenderer.close();
parcelFileDescriptor.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}, printAttributes);
}
Can someone take a look at my codes and tell me what is going wrong? Please help! Thanks!
Nevermind. It turned out the codes are ok. What I needed to do was go to the settings of my phone and change the "Display pop-up windows while running in the background" of the printer driver app to "allow", then it worked perfectly!
I will keep the question and answer here in case someone encounters the same problem.
I'm receiving notifications using OneSignal, if my app was in the background, and I click on the came notification, the app opening normally as I wanted going to the requested activity without any problem!
But if the app was not running i mean totally closed, after tapping the notification nothing happening at all! app not opening! notification going away without opening the app! any advice?
Here is the code i'm using to handle OneSignal notifications
private class NotificationOpenedHandler implements OneSignal.NotificationOpenedHandler {
// This fires when a notification is opened by tapping on it.
#Override
public void notificationOpened(OSNotificationOpenResult result) {
OSNotificationAction.ActionType actionType = result.action.type;
JSONObject data = result.notification.payload.additionalData;
String launchUrl = result.notification.payload.launchURL; // update docs launchUrl
String body = result.notification.payload.body; // update docs launchUrl
String customKey;
String openURL = null;
Object activityToLaunch = MainActivity.class;
if (data != null) {
customKey = data.optString("customkey", null);
openURL = data.optString("openURL", null);
if (customKey != null)
Log.i("OneSignalExample", "customkey set with value: " + customKey);
if (openURL != null)
Log.i("OneSignalExample", "openURL to webview with URL value: " + openURL);
}
if (actionType == OSNotificationAction.ActionType.ActionTaken) {
Log.i("OneSignalExample", "Button pressed with id: " + result.action.actionID);
if (result.action.actionID.equals("id1")) {
Log.i("OneSignalExample", "button id called: " + result.action.actionID);
activityToLaunch = Notifications.class;
} else
Log.i("OneSignalExample", "button id called: " + result.action.actionID);
}
// The following can be used to open an Activity of your choice.
Intent toActivity = new Intent(MainActivity.this, Notifications.class);
toActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
toActivity.putExtra("openURL", launchUrl);
toActivity.putExtra("body", body);
Log.i("OneSignalExample", "openURL = " + launchUrl);
//my Code
String message;
SharedPreferences sharedPreferences = getSharedPreferences(NOTES, Context
.MODE_PRIVATE);
String jsonLink = sharedPreferences.getString(NOTES_LINKS, null);
String jsonTitle = sharedPreferences.getString(NOTES_TITLE, null);
if (jsonLink != null && jsonTitle != null) {
Gson gson = new Gson();
ArrayList<String> linkList = gson.fromJson(jsonLink, new TypeToken<ArrayList<String>>() {
}.getType());
ArrayList<String> titleList = gson.fromJson(jsonTitle, new TypeToken<ArrayList<String>>() {
}.getType());
if (linkList.contains(launchUrl)) {
message = "Notification Exist!";
Log.i("Notifications","Notification Exist!");
} else {
linkList.add(launchUrl);
titleList.add(body.trim());
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(NOTES_LINKS, new Gson().toJson(linkList));
editor.putString(NOTES_TITLE, new Gson().toJson(titleList));
editor.apply();
Log.i("Notifications","Notification Stored!");
}
} else {
ArrayList<String> linkList = new ArrayList<>();
ArrayList<String> titleList = new ArrayList<>();
linkList.add(launchUrl);
titleList.add(body.trim());
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(NOTES_LINKS, new Gson().toJson(linkList));
editor.putString(NOTES_TITLE, new Gson().toJson(titleList));
editor.apply();
Log.i("Notifications","Stored");
}
// startActivity(intent);
startActivity(toActivity);
}
}
I am just digging for another issue with onesignal notification, and found this question,
I would like to answer like:
what value have you set for NotificationOpened.DEFAULT in Manifest.
"Enable" will open your application.
<application> <meta-data android:name="com.onesignal.NotificationOpened.DEFAULT" android:value="Enable" /></application>
i was facing the same issue before and was able to solve it by creating an application class and initializing oneSignal in it
public class Application extends android.app.Application {
#Override
public void onCreate() {
super.onCreate();
// OneSignal Initialization
OneSignal.startInit(this)
.inFocusDisplaying(OneSignal.OSInFocusDisplayOption.Notification)
.unsubscribeWhenNotificationsAreDisabled(true)
.setNotificationOpenedHandler(new NotificationHandler(this))
.init();
}
}
you also need to add these in your manifist
<application
android:name="Application"
...>
<meta-data android:name="com.onesignal.NotificationOpened.DEFAULT" android:value="DISABLE" />
</application>
I have this code that when I copy some text in clipboard this program paste text and application name automatically in the text box.I want paste app's name that running/on top
myClipboard.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged()
{
PackageManager pm = getApplicationContext().getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo(getPackageName(), 0);
} catch (final PackageManager.NameNotFoundException e) {
ai = null;
}
final String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)");
ClipData cp = myClipboard.getPrimaryClip();
ClipData.Item item = cp.getItemAt(0);
String text1 = item.getText().toString();
pastetext.setText(text1+"---"+applicationName);
}
});
To get the list of activities/applications installed on Android :
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
final List pkgAppsList = context.getPackageManager().queryIntentActivities( mainIntent, 0);
To check all running applications
ActivityManager actvityManager = (ActivityManager)
this.getSystemService( ACTIVITY_SERVICE );
List<RunningAppProcessInfo> procInfos = actvityManager.getRunningAppProcesses();
If you want to fetch the package name of your app or currently opened app in android, than refer this http://shortcutsandroid.blogspot.in/2015/02/how-to-get-package-name-in-android.html
Hope this helps...
I am having some problem when trying to do a recurring task in Android. Here is how I populate my list view:
public View getView(int position, View convertView, ViewGroup parent) {
String recurID;
if (convertView == null) {
convertView = inflater.inflate(R.layout.recur_listview_row, null);
viewHolder = new ViewHolder();
viewHolder.txt_ddate = (TextView) convertView.findViewById(R.id.txtDisplayRecurDate);
viewHolder.txt_damount = (TextView) convertView.findViewById(R.id.txtDisplayRecurAmount);
viewHolder.txt_dfrequency = (TextView) convertView.findViewById(R.id.txtDisplayFrequency);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
recurID = _recurlist.get(position).getRecurringID();
// Format and calculate the next payment date based on frequency
try {
String dateStr = _recurlist.get(position).getRecurringStartDate();
String frequencyStr = _recurlist.get(position).getFrequency();
Calendar cal = Calendar.getInstance();
cal.setTime(dateFormat.parse(dateStr));
if (frequencyStr.equals("Daily")) {
cal.add(Calendar.DAY_OF_MONTH, 1);
viewHolder.txt_ddate.setText("Next Payment On: " + dateFormat.format(cal.getTimeInMillis()));
cal.add(Calendar.DAY_OF_MONTH, -1);
} else if (frequencyStr.equals("Weekly")) {
cal.add(Calendar.WEEK_OF_YEAR, 1);
viewHolder.txt_ddate.setText("Next Payment On: " + dateFormat.format(cal.getTimeInMillis()));
cal.add(Calendar.WEEK_OF_YEAR, -1);
}
} catch (ParseException e) {
e.printStackTrace();
}
viewHolder.txt_dfrequency.setText(_recurlist.get(position).getFrequency().trim());
if (_recurlist.get(position).getRecurringType().equals("W")) {
viewHolder.txt_damount.setTextColor(Color.rgb(180, 4, 4));
viewHolder.txt_damount.setText("Credit $ " + amount);
} else if (_recurlist.get(position).getRecurringType().equals("D")) {
viewHolder.txt_damount.setTextColor(Color.rgb(8, 138, 8));
viewHolder.txt_damount.setText("Debit $ " + amount);
}
// Get current date
String currentDate = "Next Payment On: " + dateFormat.format(new Date());
// If current date matches with the next payment date, insert new
// transaction record
if (currentDate.equals(viewHolder.txt_ddate.getText())) {
DatabaseAdapter mDbHelper = new DatabaseAdapter(Recurring.this);
mDbHelper.createDatabase();
mDbHelper.open();
TransactionRecModel trm = new TransactionRecModel();
CategoryController cc = new CategoryController(mDbHelper.open());
trm.setDate(dateFormat.format(new Date()));
if (_recurlist.get(position).getRecurringType().equals("W")) {
trm.setType("W");
} else if (_recurlist.get(position).getRecurringType().equals("D")) {
trm.setType("D");
}
trm.setAmount(Float.parseFloat(formatAmount));
TransactionRecController trc = new TransactionRecController(mDbHelper.open());
if (trc.addTransactionRec(trm)) {
// After successfully insert transaction record, update the
// recurring start date
rm = new RecurringModel();
rm.setRecurringID(recurID);
rm.setRecurringStartDate(dateFormat.format(new Date()));
RecurringController rc = new RecurringController(mDbHelper.open());
if (rc.updateRecurringDate(rm)) {
mDbHelper.close();
}
}
}
return convertView;
}
From the code I tried to get the current date and compare with the next payment date computed based on frequency. However, with these code, it does not run in background.
Let's say I set a recurring event which will be repeating daily yesterday. But I did not run the application today. By right, the recurring should run in background and execute the recurring. But somehow, it does not.
I wonder do I need some service like AlarmManager to do this?
Thanks in advance.
EDIT
So what I've changed is the part when I try to compare the dates, if the dates matched, it will call the alarmManager and parse some values along the way:
if (currentDate.equals(viewHolder.txt_ddate.getText())) {
long when = new Date().getTime();
notificationCount = notificationCount + 1;
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent notificationIntent = new Intent(context, ReminderAlarm.class);
notificationIntent.putExtra("RecurID", recurID);
notificationIntent.putExtra("Date", dateFormat.format(new Date()));
notificationIntent.putExtra("Description", viewHolder.txt_ddesc.getText().toString());
notificationIntent.putExtra("Type", _recurlist.get(position).getRecurringType());
notificationIntent.putExtra("Amount", Float.parseFloat(formatAmount));
notificationIntent.putExtra("CategoryID", viewHolder.txt_dcat.getText().toString());
notificationIntent.putExtra("NotifyCount", notificationCount);
PendingIntent pi = PendingIntent.getBroadcast(context, notificationCount, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.set(AlarmManager.RTC_WAKEUP, when, pi);
}
And in my ReminderAlarm class, I am executing the insert and update SQL statement:
public class ReminderAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String recurID = intent.getStringExtra("RecurID");
String date = intent.getStringExtra("Date");
String description = intent.getStringExtra("Description");
String type = intent.getStringExtra("Type");
Float amount = Float.parseFloat(intent.getStringExtra("Amount"));
String categoryID = intent.getStringExtra("CategoryID");
DatabaseAdapter mDbHelper = new DatabaseAdapter(ReminderAlarm.this);
mDbHelper.createDatabase();
mDbHelper.open();
TransactionRecModel trm = new TransactionRecModel();
CategoryController cc = new CategoryController(mDbHelper.open());
trm.setDate(date);
trm.setTransDescription(description);
if (type.equals("W")) {
trm.setType("W");
} else if (type.equals("D")) {
trm.setType("D");
}
trm.setAmount(amount);
// Get the categoryID based on categoryName
String catID = cc.getCatIDByName(categoryID);
trm.setCategory(catID);
TransactionRecController trc = new TransactionRecController(mDbHelper.open());
if (trc.addTransactionRec(trm)) {
// After successfully insert transaction record, update the
// recurring start date
RecurringModel rm = new RecurringModel();
rm.setRecurringID(recurID);
rm.setRecurringStartDate(date);
RecurringController rc = new RecurringController(mDbHelper.open());
if (rc.updateRecurringDate(rm)) {
mDbHelper.close();
}
}
}
}
Your Adapter should receive data that is ready to be displayed. getView is called every time a ListView item comes onto screen, so you want to keep your work here to under 16ms if you hope to maintain 60fps scrolling. Because of this, you should do all heavy work before it gets to the Adapter.
Since database data is often not display-ready, you would typically use a Loader to get the data, and turn it into a list of "items" that are Adapter-ready. This should happen in your Activity or Fragment, and you fill the Adapter in onLoadFinished. This often means creating a new POJO to represent the display data.
Best place to start is the Loader tutorial.
If you want to set a recurring task, you should use the AlarmManager, as you suspected. The AlarmManager would typically trigger a BroadcastManager, which in turn would spawn a Service to do the work.
Follow the AlarmManager tutorial for more details.
First of all, I searching for my question many times in Google but I didn't find what I want.
My Question is: Is there any way to open application in Android by "label name" where on the other hand the package name is "knowing" ?
My approach that I used to do this is by creating two ArrayList and store the package name and label name in each one, then, I matching the label name with package name after I converted them to lowercase in order to be the same letters to see if there are matching, if matching , then I launch the application by getting its package name.
the problem that I faced it, the package name sometimes didn't have or matching the same name in label name, based on the application developer what he had write the package name.
for example: if I want to open gmail , based on my method I cannot because the package name is com.google.android.gm and label name is gmail , I apologized to the prolongation ,thanks in advanced.
My code:
private void getAllApps() {
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> activities = getPackageManager()
.queryIntentActivities(mainIntent, 0);
for (ResolveInfo resolveInfo : activities) {
appsName.add(resolveInfo.loadLabel(getPackageManager()).toString()
.toLowerCase());
pkgsName.add(resolveInfo.activityInfo.packageName.toString());
}
}
private void openApplication(String appName) {
String packageName = null, appNameLowerCase = null, pkgNameLowerCase = null;
// matching the package name with label name
if (appsName.contains(appName)) {
appNameLowerCase = appName.trim().replace(" ", "");
for (int i = 0; i < pkgsName.size(); i++) {
pkgNameLowerCase = pkgsName.get(i).trim().toLowerCase();
if (pkgNameLowerCase
.matches("(.*)" + appNameLowerCase + "(.*)")) {
packageName = pkgsName.get(i);
break;
}
}
}
// to launch the application
Intent i;
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage(packageName);
if (i == null)
throw new PackageManager.NameNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
} catch (PackageManager.NameNotFoundException e) {
}
}
thanks for all replies, i solve it by #CommonsWare solution and it works correctly :
class Applications {
private String packageName;
private String labelName;
}
private void getAllApps() {
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> activities = getPackageManager()
.queryIntentActivities(mainIntent, 0);
for (ResolveInfo resolveInfo : activities) {
Applications applications = new Applications();
applications.labelName = resolveInfo.loadLabel(getPackageManager())
.toString().toLowerCase();
applications.packageName = resolveInfo.activityInfo.packageName
.toString();
applicationsArrayList.add(applications);
}
}
private void openApplication(String appName) {
String packageName = null;
// matching the package name with label name
for (int i = 0; i < applicationsArrayList.size(); i++) {
if (applicationsArrayList.get(i).labelName.trim().equals(
appName.trim())) {
packageName = applicationsArrayList.get(i).packageName;
break;
}
}
// to launch the application
Intent i;
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage(packageName);
if (i == null)
throw new PackageManager.NameNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
} catch (PackageManager.NameNotFoundException e) {
}
}
Try this
public List<ApplicationInfo> getApplicationList(Context con){
PackageManager p = con.getPackageManager();
List<ApplicationInfo> info = p.getInstalledApplications(0);
String example = info.get(0).packageName.toString();
return info;
}