I'm creating a Music Player. I know that in Api 29 and above , we should Send Request to User for deleting Music file in MediaStore.
and this is where result get back in Api 29 and above:
intentSenderRequest = registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
getActivity().getApplication().getContentResolver().delete(deleteUri, null, null);
}
Toast.makeText(getActivity(), deleteAudioModel.getData(), Toast.LENGTH_SHORT).show();
File file = new File(deleteAudioModel.getData());
file.delete();
adapter.itemDeleted(itemForDelete);
} else {
Toast.makeText(getActivity(), "Not Deleted", Toast.LENGTH_SHORT).show();
}
}
});
but the music just delete from MediaStore and remain in device storage.
I tried to delete it after User permission by MediaStore.Audio.Media.DATA and File.delete method,
but I've got no result.
is there any way for delete file in Api 29 and above?
Related
I have inherited an older customization to the Purchase Receipts / PO302000 screen that I'm trying to upgrade, and it had customization code to import Lot/Serial nbrs from an Excel spreadsheet. It all seems to work alright, except that at the end, it errors out when pressing a button as follows:
Base.Actions["LSPOReceiptLine_binLotSerial"].Press();
Here's the entire code:
public virtual void importAllocations()
{
try
{
if (Base.transactions.Current != null)
{
var siteid = Base.transactions.Current.SiteID;
if (Base.splits.Select().Count == 0)
{
if (this.NewRevisionPanel.AskExt() == WebDialogResult.OK)
{
const string PanelSessionKey = "ImportStatementProtoFile";
PX.SM.FileInfo info = PX.Common.PXContext.SessionTyped<PXSessionStatePXData>().FileInfo[PanelSessionKey] as PX.SM.FileInfo;
System.Web.HttpContext.Current.Session.Remove(PanelSessionKey);
if (info != null)
{
byte[] filedata = info.BinData;
using (NVExcelReader reader = new NVExcelReader())
{
Dictionary<UInt32, string[]> data = reader.loadWorksheet(filedata);
foreach (string[] textArray in data.Values)
{
if (textArray[0] != GetInventoryCD(Base.transactions.Current.InventoryID))
{
throw (new Exception("InventoryID in file does not match row Inventory ID"));
}
else
{
//Find the location ID based on the location CD provided by the Excel sheet...
INLocation inloc = PXSelect<INLocation,
Where<INLocation.locationCD, Equal<Required<INLocation.locationCD>>,
And<INLocation.siteID, Equal<Required<INLocation.siteID>>>>>.Select(Base
, textArray[1]
, Base.transactions.Current.SiteID);
Base.splits.Insert(new POReceiptLineSplit()
{
InventoryID = Base.transactions.Current.InventoryID,
LocationID = inloc.LocationID, //Convert.ToInt32(textArray[1]), //Base.transactions.Current.LocationID,
LotSerialNbr = textArray[2],
Qty = Decimal.Parse(textArray[3])
});
}
}
}
}
}
}
}
Base.Actions["LSPOReceiptLine_binLotSerial"].Press();
}
catch (FileFormatException fileFormat)
{
// Acuminator disable once PX1053 ConcatenationPriorLocalization [Justification]
throw new PXException(String.Format("Incorrect file format. File must be of type .xlsx", fileFormat.Message));
}
catch (Exception ex)
{
throw ex;
}
}
Now, there seems to be no such button - and I have no idea what it would be called now, or if it even still exists. I don't even really know what this action did.
Any ideas?
Thanks much...
That logic has been moved into the PX.Objects.PO.GraphExtensions.POReceiptEntryExt.POReceiptLineSplittingExtension. That action was doing the following in the PX.Objects.PO.LSPOReceiptLine
// PX.Objects.PO.LSPOReceiptLine
// Token: 0x0600446F RID: 17519 RVA: 0x000EE86C File Offset: 0x000ECA6C
public override IEnumerable BinLotSerial(PXAdapter adapter)
{
if (base.MasterCache.Current != null)
{
if (!this.IsLSEntryEnabled((POReceiptLine)base.MasterCache.Current))
{
throw new PXSetPropertyException("The Line Details dialog box cannot be opened because changing line details is not allowed for the selected item.");
}
this.View.AskExt(true);
}
return adapter.Get();
}
Now it is called ShowSplits and is part of the POReceiptLineSplittingExtension extension.
// PX.Objects.PO.GraphExtensions.POReceiptEntryExt.POReceiptLineSplittingExtension
// Token: 0x06005359 RID: 21337 RVA: 0x00138621 File Offset: 0x00136821
public override IEnumerable ShowSplits(PXAdapter adapter)
{
if (base.LineCurrent == null)
{
return adapter.Get();
}
if (!this.IsLSEntryEnabled(base.LineCurrent))
{
throw new PXSetPropertyException("The Line Details dialog box cannot be opened because changing line details is not allowed for the selected item.");
}
return base.ShowSplits(adapter);
}
Given the fact that ShowSplits is defined in the LineSplittingExtension originally it may be referred to as "LineSplittingExteions_ShowSplits" or "POReceiptLineSplittingExtension_ShowSplits". I would suggest including that POReceiptLineSplittingExtension as part of your extension and simply call the Base1.ShowSplits
I am trying to send push notifications through the firebase admin sdk, but the image somehow is not displayed in the push notification.
What's weird is that when I use an invalid key in the notifications object (like image) I get an error. So I assume I got the right keys specified. Documentation for the Notification can be found here.
The following code successfully sends a push notification but there is no image displayed on the users phone:
const admin = require('firebase-admin');
const app = admin.initializeApp({...}); // authenticated with credentials json file
await app.messaging().sendMulticast({
notification: {
title: "hello User",
body: "This is a push notification with an image",
imageUrl: "https://example.com/myPublicImage.png",
},
tokens: ["device_token_1", "device_token_2","..."]
});
Change imageUrl key to image in notification being sent by Firebase Admin SDK. I checked with imageUrl key, it does not work, rather,
it gives null to remoteMessage.getNotification().getImageUrl() in app.
In node.js server, you can create post request to send the Firebase message using Firebase Admin SDK:
Request.post({
"headers": {"Authorization":auth_key_string, "content-type": "application/json" },
"url": "https://fcm.googleapis.com/fcm/send",
"body": JSON.stringify({
"registration_ids" :receiver_token ,
"notification" : {
"title": title,
"body" : message,
"image":imageUrlVal
}
})
}, (error, response, body) => {
if(error) {
return console.dir(error);
}
console.dir(JSON.parse(body));
});
Now, handle this message from FirebaseActivity in Android App code.
In onMessageReceived method add this lines.
if (remoteMessage.getNotification() != null) {
// Since the notification is received directly from
// FCM, the title and the body can be fetched
// directly as below.
Log.d(TAG, "Message Received: " + "YES");
Bitmap bitmap = null;
try {
bitmap = getBitmapfromUrl(remoteMessage.getNotification().getImageUrl().toString());
} catch (Exception e) {
e.printStackTrace(); }
try {
showNotification(
remoteMessage.getNotification().getTitle(),
remoteMessage.getNotification().getBody(),bitmap );
} catch (IOException e) {
e.printStackTrace();
}
}
Define getBitmapfromUrl() as below:
public Bitmap getBitmapfromUrl(String imageUrl) {
try {
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
return BitmapFactory.decodeStream(input);
} catch (Exception e) {
Log.e("awesome", "Error in getting notification image: " + e.getLocalizedMessage());
return null;
}
}
showNotification() can be defined as:
public void showNotification(String title,
String message, Bitmap bitmap) throws IOException {
Intent intent
= new Intent(this, NextPageActivity.class);
// Assign channel ID
String channel_id = "notification_channel";
// Here FLAG_ACTIVITY_CLEAR_TOP flag is set to clear
// the activities present in the activity stack,
// on the top of the Activity that is to be launched
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Pass the intent to PendingIntent to start the
// next Activity
PendingIntent pendingIntent
= PendingIntent.getActivity(
this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder builder
= new NotificationCompat
.Builder(getApplicationContext(), channel_id)
.setSmallIcon(R.drawable.app_icon)
.setAutoCancel(true)
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000})
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent);
// A customized design for the notification can be
// set only for Android versions 4.1 and above. Thus
// condition for the same is checked here.
if (Build.VERSION.SDK_INT
>= Build.VERSION_CODES.JELLY_BEAN) {
Log.d(TAG, "Higher Version: ");
builder = builder.setContent(
getCustomDesign(title, message));
if (bitmap != null) {
builder.setLargeIcon(bitmap)
.setStyle(
new NotificationCompat.BigPictureStyle()
.bigPicture(bitmap)
.bigLargeIcon(null)
.setBigContentTitle(title)
.setSummaryText(message)
);
}
} // If Android Version is lower than Jelly Beans,
// customized layout cannot be used and thus the
// layout is set as follows
else {
Log.d(TAG, "Lower Version: ");
builder = builder.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.drawable.app_icon);
}
// Create an object of NotificationManager class to
// notify the
// user of events that happen in the background.
NotificationManager notificationManager
= (NotificationManager) getSystemService(
Context.NOTIFICATION_SERVICE);
// Check if the Android Version is greater than Oreo
if (Build.VERSION.SDK_INT
>= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel
= new NotificationChannel(
channel_id, "web_app",
NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(
notificationChannel);
}
notificationManager.notify(0, builder.build());
}
getCustomDesign() can be defined as:
private RemoteViews getCustomDesign(String title,
String message) {
#SuppressLint("RemoteViewLayout") RemoteViews remoteViews =
new RemoteViews(getApplicationContext().getPackageName(),
R.layout.notification);
remoteViews.setTextViewText(R.id.title, title);
remoteViews.setTextViewText(R.id.message, message);
remoteViews.setTextViewText(R.id.note_button, "Reply");
remoteViews.setImageViewResource(R.id.icon, R.drawable.app_icon);
//remoteViews.setImageViewResource(R.id.message_image, R.drawable.app_icon);
return remoteViews;
}
I am trying to download multiple files from gridView by selecting checkbox( on SharePoint site), Actually it will fetch the file using SharePoint ID from list in the SharePoint site and write it my documents folder and then zip it.
all the functionalities working in development server, I am able to download as zip file in the my documents folder in the system.
Note: The same code deployed to QA environment, I tried to download it, but I am getting the 403 forbidden error. I could not able to download it.
Could someone please help me on this issue.
protected void btnDownload_Click(object sender,EventArgs e)
{
int counter=0;
bool dataSel=false;
for(int i=0;i<gridviewestimates.rows.count; i++)
{
checkbox chkselect=
(checkboc)gridviewestimates.rows[i].findcontrol("chkselect");
try
{
if(chkselect.checked)
{
counter++;
Label lblspitemid=
(label)gridviewestimates.rows[i].findcontrol("lblspitemid");
addfiletodictionary("Estimate
Documents",convert.ToInt32(lblSPItemId.Text));
dataSel=true;
}
}
catch(Exception ex) {throw ex;}
}
if(counter <=0)
{
page.clientscript.registerstartupscript(GetType(),"msgbox","alert('Please
select the checkbox to download files');",true);
}
if(dataSel)
{
callzipmethod();
}
}
private void callzipmethod()
{
string path=path.combine(environment.getfolderpath
(environment.specialfolder.mydocument),"KKM Estimate Documents");
try
{
string sourcePath=path;
string
docPath=environment.getfolderpath(environment.specialfolder.mydocuments);
string
destinationPath=docPath+"\\"+"KKM_Estimates_"+datetime.now.tostring
("MM_dd_yyyy HH.mm tt")+".zip";
string[] filenames=Directory.GetFiles(sourcePath);
using(ZipOutputStream outputstream=new ZipOutputStream(File.Create
(destionationPath)))
{
outputstream.setlevel(9);
byte[] buffer=new byte[40000];
foreach(string file in filenames)
{
ZipEntry entry=new ZipEntry(Path.GetFileName(file));
entry.DateTime=DateTime.Now;
outputstream.PutNextEntry(entry);
using(FileStream fs=File.OpenRead(file))
{
int sourceBytes;
do
{
sourceBytes=fs.Read(buffer,0,buffer.Length);
outputstream.Write(buffer,0,sourceBytes);
}while(sourceBytes > 0);
}
}
outputstream.Finish();
outputstream.Close();
Page.clientscript.registerstartupscript(GetType()."msgbox","alert
('KKM_Estiates_
"+DateTime.Now.ToString("MM_dd_yyyy HH.mm tt")+ ".zip downloaded
inside MyDocuments folder');",true);
}
}
catch(Exception ex)
{
throw ex;
}
string[] files=Directory.GetFiles(path);
foreach(string file in files)
{
var name=new FileInfo(file).Name;
File.Delete(file);
}
if(Directory.Exists(path))
{
Directory.Delete(path);
}
}
private void AddFileToDictionary(string libraryName,int documentId)
{
SPSite site=new SPSite(SPContext.Current.Web.Url);
SPWeb web=site.OpenWeb();
SPList docLib=web.Lists[libraryName];
SPListItem item=docLib.GetItemById(documentId);
SPFile docFile=item.File;
byte[] b=docFile.OpenBinary();
string date=DateTime.Now.ToString("MM_dd_yyyy HH.mm tt");
Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "KKM Estimate Documents"));
string path=Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "KKM Estimate Documents");
string fullPath=path+"\\"+docFile.Name;
FileStream stream=new FileStream(fullPath,FileMode.Create);
stream.Write(b,0,b.length);
stream.Close();
}
Project setup:
<java.version>1.8</java.version>
<spring.version>4.3.9.RELEASE</spring.version>
<spring.boot.version>1.4.3.RELEASE</spring.boot.version>
We have a REST controller that has a method to upload file like this:
#PostMapping("/spreadsheet/upload")
public ResponseEntity<?> uploadSpreadsheet(#RequestBody MultipartFile file) {
if (null == file || file.isEmpty()) {
return new ResponseEntity<>("please select a file!", HttpStatus.NO_CONTENT);
} else if (blueCostService.isDuplicateSpreadsheetUploaded(file.getOriginalFilename())) {
return new ResponseEntity<>("Duplicate Spreadsheet. Please select a different file to upload",
HttpStatus.CONFLICT);
} else {
try {
saveUploadedFiles(Arrays.asList(file));
} catch (IOException e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
return new ResponseEntity("Successfully uploaded - " + file.getOriginalFilename(), new HttpHeaders(),
HttpStatus.OK);
}
}
UPDATE:
I've tried this approach from an old example I found, but it doesn't compile cleanly, the MockMvcRequestBuilders.multipart method is not defined....
#Test
public void testUploadSpreadsheet_Empty() throws Exception {
String fileName = "EmptySpreadsheet.xls";
String content = "";
MockMultipartFile mockMultipartFile = new MockMultipartFile(
"emptyFile",
fileName,
"text/plain",
content.getBytes());
System.out.println("emptyFile content is '" + mockMultipartFile.toString() + "'.");
mockMvc.perform(MockMvcRequestBuilders.multipart("/bluecost/spreadsheet/upload")
.file("file", mockMultipartFile.getBytes())
.characterEncoding("UTF-8"))
.andExpect(status().isOk());
}
I believe MockMvcRequestBuilders.multipart() is only available since Spring 5. What you want is MockMvcRequestBuilders.fileUpload() that is available in Spring 4.
I our app (Xamarin C#) we download files from a server. At the end of a succeful download we get the URI to the newly-downloaded file and from the URI we get the file path:
Android.Net.Uri uri = downloadManager.GetUriForDownloadedFile(entry.Value);
path = u.EncodedPath;
In Android 4.4.2 and in Android 5 the uri and path look like this:
uri="file:///storage/emulated/0/Download/2.zip"
path = u.EncodedPath ="/storage/emulated/0/Download/2.zip"
We then use path to process the file.
The problem is that in Android 6 (on a real Nexus phone) we get a completely different uri and path:
uri="content://downloads/my_downloads/2802"
path="/my_downloads/2802"
This breaks my code by throwing a FileNotFound exception. Note that the downloaded file exists and is in the Downloads folder.
How can I use the URI I get from Android 6 to get the proper file path so I can to the file and process it?
Thank you,
donescamillo#gmail.com
I didn't get your actual requirement but it looks like you want to process file content. If so it can be done by reading the file content by using file descriptor of downloaded file. Code snippet as
ParcelFileDescriptor parcelFd = null;
try {
parcelFd = mDownloadManager.openDownloadedFile(downloadId);
FileInputStream fileInputStream = new FileInputStream(parcelFd.getFileDescriptor());
} catch (FileNotFoundException e) {
Log.w(TAG, "Error in opening file: " + e.getMessage(), e);
} finally {
if(parcelFd != null) {
try {
parcelFd.close();
} catch (IOException e) {
}
}
}
But I am also looking to move or delete that file after processing.
May you an build your URI with the download folder :
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toURI();
It's work. #2016.6.24
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals( action)) {
DownloadManager downloadManager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor c = downloadManager.query(query);
if(c != null) {
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
String downloadFileUrl = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
startInstall(context, Uri.parse(downloadFileUrl));
}
}
c.close();
}
}
}
private boolean startInstall(Context context, Uri uri) {
if(!new File( uri.getPath()).exists()) {
System.out.println( " local file has been deleted! ");
return false;
}
Intent intent = new Intent();
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction( Intent.ACTION_VIEW);
intent.setDataAndType( uri, "application/vnd.android.package-archive");
context.startActivity( intent);
return true;
}