Neither on Android nor on iOS the sound file referenced by a LocalNotification instance is played (check the sample code below). On Android the system's standard sound is played. Anyone knows what I am doing wrong here?
#Override
protected void postMain(Form f) {
Container contentPane = f.getContentPane();
contentPane.setLayout(new BorderLayout(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE));
contentPane.setUIID("ToastBar");
Button btn = new Button("create Notification");
btn.addActionListener((e) -> {
scheduleNotification(Display.getInstance(), 0, "Title", "Body", "notification_sound_file.mp3", System.currentTimeMillis() + 1000);
});
contentPane.add(BorderLayout.CENTER, btn);
}
private void scheduleNotification(Display dsp, int nId, String nTitle, String nBody, String soundFileName, long scheduleTime) {
LocalNotification ntf = new LocalNotification();
ntf.setId(nId + " " + scheduleTime);
ntf.setAlertTitle(nTitle);
ntf.setAlertBody(nBody + " " + scheduleTime);
ntf.setAlertSound("/" + soundFileName);
Log.p("scheduling ntf ("+nTitle+","+ ntf.getAlertBody() +","+ ntf.getAlertSound());
dsp.scheduleLocalNotification(ntf, scheduleTime, LocalNotification.REPEAT_NONE);
}
Note: notification_sound_file.mp3 does exist in my default package!
If you want to get the sound file from device storage, then it can't detect directly
Instead of using this
ntf.setAlertSound("/" + soundFileName);
Try this
ntf.setAlertSound(Environment.getExternalStorageDirectory().getAbsolutePath() + "Folder_Name/" + soundFileName);
This will locate your file and your specific sound will play. One more thing add "android.permission.READ_EXTERNAL_STORAGE" permission also in manifest.
Best of luck.
The sound file needs to be a path to a file in FileSystemStorage which must always be fully qualified. You need to copy the file into the filesystem ideally under the app directory see https://www.codenameone.com/how-do-i-use-storage-file-system-sql.html
Related
I am having real trouble getting the thumbnail to show in an Ionic app. I've tried to emulate it on an android device, no go, I've tried to launch the app on my phone, also no go. I tried varying the src parameter in the [ion-img], and that didn't work. So I thought I would ask Stack Overflow.
The Ionic app is a simple one. I basically have a homepage.html and ts file. The app runs one in every way except that it is not displaying the thumbnail. I have the relevant ts code looking like the following:
async startRecord(){
console.log("Entering record x");
let base64 = null;
const option: CaptureVideoOptions = {
limit: 1,
duration: 5,
quality: 100
};
var dateObj = new Date();
var minutes = dateObj.getMinutes().toString();
let minStr = "";
if(minutes.length<=1){
minStr = "0" + minutes;
}
else{
minStr = minutes;
}
var date = "Date: " + dateObj.getMonth() + "-" + dateObj.getDate() + "-" + dateObj.getFullYear() + " Time: " + dateObj.getHours() + ":" + minStr;
console.log("date",date);
const id:string = uuid();
this.mediaCapture.captureVideo(option).then(async (mediaFile: MediaFile[]) => {
this.video = mediaFile[0];
this.keys = Object.keys(this.video);
await this.createThumbnail(this.video?.fullPath);
const video = {
id: id,
fullPath: this.video?.fullPath,
name: this.video?.name,
userLabel: 'undecided',
thumbnail: this.thumbnail,
serverLabel: "none",
size: this.video?.size,
dateVideoTaken: date,
};
console.log(video);
await this.util.storeVide(video);
await this.getAllVideos();
}, (error: CaptureError) => {
console.log(error.code);
alert(error.code);
});
}
I call the createThumbnail from video-capture, and that also seems to run fine. I'm using the console.log to verify that the thumbnail is successfully been created on my emulator or phone, and it is.
async createThumbnail(path){
console.clear();
console.log('Full Video Path ', path);
var numstr = new Date().getTime();
var option:CreateThumbnailOptions = {fileUri: path ,width:160, height:206, atTime:1, outputFileName: 'thumbnail' + numstr, quality:100 };
const thumbnail = await this.VideoEditor.createThumbnail(option);
console.log("Thumbnail desc.", thumbnail);
this.thumbnail = thumbnail;
}
I check the thumbnail by physically going to the location on my phone, and the image is indeed there. I then try to represent it as a thumbnail for this particular video, using this text in the HTML page:
<ion-thumbnail slot="start" class="customized-image" id="thumbnail" (click)="openVideo(video.fullPath)" >
<!-- <img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"> -->
<img src="{{video?.thumbnail}}">
</ion-thumbnail>
This works fine when I call a generic thumbnail from gravatar but somehow fails when calling the thumbnail.
I tried mixing this problem all day yesterday and thought I would ask the Stack Overflow community.
Please feel free to ask for more code If this doesn't describe my problem well enough.
Also, the f key no longer works on my computer, hence the misspellings in my text. I have to copy-paste the key when I want to use it.
Here is a console log sample:
I am new to Unity and Android development, but please do not mark this as a duplicate - I've looked all over the stacks for an answer to this, but similar topics and questions haven't yielded any working solutions, or are wanting on details, or outdated, or seem not to fit my specific need.
Ok, I have a quiz app built from following part 1 & 2 of this tutorial. That link contains all the source files anyone might need for reference, and everything works fine on ios and in the unity editor, fyi.
The trouble is with the loadGameData function from the DataController script in Android. Again, everything works fine in iOS and the unity editor, but when I make an Android sdk, the quiz is blank and the console says the data couldn't be loaded.
Here is how the function is currently written (full file in tutorial link):
private void LoadGameData ()
{
string filePath = Path.Combine (Application.streamingAssetsPath, gameDataFileName);
if (File.Exists (result))
{
string dataAsJson = File.ReadAllText (result);
GameData loadedData = JsonUtility.FromJson<GameData> (dataAsJson);
allRoundData = loadedData.allRoundData;
} // #if(File.Exists...
else
{
Debug.LogError ("Cannot load game data!");
} // #else
} // #LoadGameData
If you check the same tutorial on youtube, you'll see lots of people have noted the same problem with the Android build and have been left unanswered. Same goes with unity forums - that's one reason why I don't think this question is a duplicate and could be helpful to others in a similar situation.
I've found that Android has always been sorta tricky with this and that there used to different ways of accessing a file based on platform, but these days "Application.streamingAssetsPath" should find the streaming assets directory on any platform, even Android.
What I've also learned is that in android, even if the path is correct, the file is compressed and will only return a url. So the url needs to be converted using unity's WWW class. I get that, but as of yet, I haven't been able to re-write my loadGameData function to work properly and load the allRoundData array.
Here's an example of some things I've tried:
IEnumerator androidData()
{
string filePath = Path.Combine (Application.streamingAssetsPath, gameDataFileName);
if (filePath.Contains("://"))
{
WWW www = new WWW(filePath);
yield return www;
result = www.text;
} // #if(filePath.Contains
} // #androidData
private void LoadGameData ()
{
androidData();
if (File.Exists (result))
{
string dataAsJson = File.ReadAllText (result);
GameData loadedData = JsonUtility.FromJson<GameData> (dataAsJson);
allRoundData = loadedData.allRoundData;
} // #if(File.Exists...
else
{
Debug.LogError ("Cannot load game data!");
} // #else
} // #LoadGameData
I know I'm close, and this is probably simple -- but I just can't seem to get to the finish line on this. Can some one help me figure out how to write the loadGameData function so it will load this allRoundData array on android?
An example code would be awesome and much appreciated, not just by me, but I'm sure many others would appreciate it also - Thank you!
UPDATE:
Based on the first answer, I've tested some code that works on the unity editor, but crashes in Android. In the Unity editor, I get the "file already exists" message. Here is the code I've tested:
Already had: private string gameDataFileName = "data.json";
I added the copyFile call above loadGameDate in Start() and wrote the copy file and loadGameData functions like so ..
int copyFileToPersistentDataPath(string gameDataFileName)
{
string persistentPath = Application.persistentDataPath + "/" + gameDataFileName;
try
{
//Copy only if gameDataFileName does not exist
if (!System.IO.File.Exists(persistentPath))
{
string path = System.IO.Path.Combine(Application.streamingAssetsPath, gameDataFileName);
WWW www = new WWW(path);
while (!www.isDone) { }
System.IO.File.WriteAllBytes(persistentPath, www.bytes);
Debug.Log(gameDataFileName + " Successfully Copied File to " + persistentPath);
return 1;
}
else
{
Debug.Log(gameDataFileName + " File already exist here. There is no need to copy it again");
return 0;
}
}
catch (Exception e)
{
Debug.Log(gameDataFileName + " Failed To Copy File. Reason: " + e.Message);
return -1;
}
}
private void LoadGameData ()
{
string tempPath = Path.Combine(Application.persistentDataPath, gameDataFileName);
string dataAsJson = File.ReadAllText(tempPath);
GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
allRoundData = loadedData.allRoundData;
} // #LoadGameData
This works with or without the call to copy the file in the editor, but crashes either way in Android.
I ended up putting the files in a Resources folder and going the resources.load a json file into a text asset and throw that into a string to parse route. I now have two different load functions, one that works in ios etc. and one that works in android. Here is the android function (the resourcesGameDataFile does not have the .json extension):
public void LoadDataForAndroid()
{
TextAsset dataFile = Resources.Load(resourcesGameDataFile) as TextAsset;
string dataAsJson = dataFile.ToString();
GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
allRoundData = loadedData.allRoundData;
Debug.Log ("Android data loaded with" + resourcesGameDataFile);
} // #LoadDataForAndroid
And this works in the unity editor and in Bluestacks (android simulator).
As for loading and saving games, this is a duplicate. I marked and remove this as a duplicate because the answer in the duplicated questions did not explain how to read from the StreamingAssets folder. It only talked about saving and loading data.
Make sure that Write Permission is set to External (SDCard).
The first thing to do is to copy the file from StreamingAssets to the persistentDataPath location.
I've found reading data from Application.streamingAssetsPath problematic but I use two methods to solve this.
int copyFileToPersistentDataPath(string fileNameWithExtensionName)
{
string persistentPath = Application.persistentDataPath + "/" + fileNameWithExtensionName;
try
{
//Copy only if fileNameWithExtensionName does not exist
if (!System.IO.File.Exists(persistentPath))
{
string path = System.IO.Path.Combine(Application.streamingAssetsPath, fileNameWithExtensionName);
WWW www = new WWW(path);
while (!www.isDone) { }
System.IO.File.WriteAllBytes(persistentPath, www.bytes);
Debug.Log(fileNameWithExtensionName + " Successfully Copied File to " + persistentPath);
return 1;
}
else
{
Debug.Log(fileNameWithExtensionName + " File already exist here. There is no need to copy it again");
return 0;
}
}
catch (Exception e)
{
Debug.Log(fileNameWithExtensionName + " Failed To Copy File. Reason: " + e.Message);
return -1;
}
}
If that does not work for you, use the method with WebClient below:
void copyFileToPersistentDataPath(string fileNameWithExtensionName)
{
string path = System.IO.Path.Combine(Application.streamingAssetsPath, fileNameWithExtensionName);
string persistentPath = Application.persistentDataPath + "/" + fileNameWithExtensionName;
Debug.Log("Dir: " + persistentPath);
WebClient webClient = new WebClient();
webClient.Proxy = null;
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadComplete);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnUpdateDownloadProgress);
Uri uri = new Uri(path);
webClient.DownloadFileAsync(uri, persistentPath);
}
void OnDownloadComplete(object sender, AsyncCompletedEventArgs e)
{
Debug.Log("Finished Downloading: " + e.Error.Message);
}
void OnUpdateDownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
Debug.Log("Uploading Progreess: " + e.ProgressPercentage);
}
File Copy Usage:
copyFileToPersistentDataPath("yourFileName.txt");
After copying the file, you can then read and convert it to Json like this:
string fileNameWithExtensionName = "questionfile.txt";
string tempPath = Path.Combine(Application.persistentDataPath, fileNameWithExtensionName);
string dataAsJson = File.ReadAllText(fileNameWithExtensionName);
GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
I'm using ngCordova inside an Ionic mobile app. In one of my services, I need to delete files I've written previously with $cordovaFile
remove: function (card) {
//remove a card from the store
var index = cardStore.indexOf(card);
if (index > -1) {
//remove the image files
$ionicPlatform.ready(function () {
if (card.imgFrontUrl) {
$cordovaFile.checkFile(cordova.file.externalRootDirectory, "vid-front-" + card.id + ".jpg").then(function () {
$cordovaFile.removeFile(cordova.file.externalRootDirectory, "vid-front-" + card.id + ".jpg").then(function (result) {
console.log("File '" + card.imgFrontUrl + "' deleted", JSON.stringify(result));
}, function (err) {
console.error("Failed to delete file '" + card.imgFrontUrl + "'", JSON.stringify(err));
});
}, function(err) {
console.log("File '" + card.imgFrontUrl + "' does not exist", JSON.stringify(err));
});
}
Everything claims to be successful. In my logs, I see:
14 337901 log File 'cdvfile://localhost/sdcard/vid-front-49444.jpg' deleted, {"success":true,"fileRemoved":{"isFile":true,"isDirectory":false,"name":"vid-front-49444.jpg","fullPath":"/vid-front-49444.jpg","filesystem":"<FileSystem: sdcard>","nativeURL":"file:///storage/emulated/0/vid-front-49444.jpg"}}
At this point I think it's a bug in $cordovaFile or other platform issue.
Any ideas out there?
Short answer: it works on the device. But if you're viewing the files on the device through MTP (e.g. mounted through Windows Explorer), you may not see the change reflected immediately or at all until a device restart. Use a file browser app on the device as a sanity check instead if you're facing this issue.
I have some log files in my application, and I want to make a zip file with this logs, and send it via Instabug, when I shake my phone and press on "Report a Bug" or "Send Feedback".
This is the code from my Application:
Instabug.initialize(this)
.setAnnotationActivityClass(InstabugAnnotationActivity.class)
.setShowIntroDialog(true, PSTimelineActivity.class)
.enableEmailField(true,false)
.setEnableOverflowMenuItem(true)
.setDebugEnabled(true)
.setBugHeaderText("Error")
.attachFileAtLocation(Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
As you can see, I select the file that should be attached, but I also need to make that file from my log file, just after I shook the phone (so it will take the latest logs), and before pressing any of the 2 buttons to report.
I have the archive function, I just don't know where I could put it so this would work. Any ideeas?
I initialised Instabug like this:
Instabug.initialize(this)
.setAnnotationActivityClass(InstabugAnnotationActivity.class)
.setShowIntroDialog(true, PSTimelineActivity.class)
.enableEmailField(true,false)
.setEnableOverflowMenuItem(true)
.setDebugEnabled(true)
.setBugHeaderText("Error")
.setPreSendingRunnable(new Runnable() {
#Override
public void run() {
String[] files = new String[2];
files[0] = Environment.getExternalStorageDirectory() + "/Passenger/passenger_log.txt";
files[1] = Environment.getExternalStorageDirectory() + "/Passenger/passenger_log2.txt";
Compress compress = new Compress(files, Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
compress.zip(new CrudStateCallback() {
#Override
public void onResponse(String string) {
Log.i("", "ended making the archive");
}
});
}
})
.attachFileAtLocation(Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
Following Hassan Ibraheem's advice, and now I create the .zip in the preSendingRunnable.
I need to implement a service in android that must be able to monitor a folder to detect a certain file and read what it contains. I'm having a strange behavior with my code and I can't find the reason. This is my relevant code.
public void onCreate(){
lectorFichCSV = new LectorFichCSV(); //object to read CSV files
ftpFileObserver = new FileObserver(filePath.getAbsolutePath()){
public void onEvent(int event, String file) {
if((FileObserver.CREATE & event) != 0){
Log.i("INFO: ", filePath.getAbsolutePath() + "/" + file + " is created");
if(file.substring(0,3).equals("RVE")){ //If file is created and the one I expect
try{
Log.i("INFO: ", "We have a RVE answer");
is = new FileInputStream(filePath + "/" + file);
lineaVent = lectorFichCSV.parseCSVFileAsList(is); //Get information in a list
//Get dao from ORMLite
dao = getHelper().getLineaVentDao();
Iterator<String[]> iterator = lineaVent.iterator();
if(iterator.hasNext()){
String[] aux = iterator.next();
Log.i("INFO:", "CodLineaVent "+aux[0]);
if(aux[2].equals("S")){
//Update DB information accordin to my file
UpdateBuilder<LineaVent, Integer> updateBuilder = dao.updateBuilder();
updateBuilder.where().eq("_id", aux[0]);
updateBuilder.updateColumnValue("valido", true);
updateBuilder.updateColumnValue("saldo", true);
updateBuilder.update();
lineaVent.clear();
}else if(aux[2].equals("N")){
UpdateBuilder<LineaVent, Integer> updateBuilder = dao.updateBuilder();
updateBuilder.where().eq("_id", aux[0]);
updateBuilder.updateColumnValue("saldo", false);
updateBuilder.update();
lineaVent.clear();
}
File fileToDel = new File(filePath + "/" + file);
fileToDel.delete();
}
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(SQLException e){
e.printStackTrace();
}
}
I debugged the code and sometimes is working and sometimes I get lineaVent.size() == 0. I'm going crazy with this, I'm thinking, is it possible that events occurs faster than the creation of my file? that would be the reason when I tried to parse my CSV file into my List object is size = 0? In that case I'm not getting any FileNotFoundException.
Any help will be appreciate. Thank you.
I am not an expert with the inotify POSIX API that, IIRC, underlies FileObserver. However, given that there are separate events for CREATE, MODIFY, and CLOSE_WRITE, it stands to reason that the CREATE event is solely for file creation -- in other words, allocating a new entry in the filesystem for the file. That would either create an empty file, or perhaps a file with some initial load of bytes, but where other MODIFY calls might be needed to write out the full contents. CLOSE_WRITE would then be called to indicate that whoever was writing to the file has now closed their file handle.
Hence, if you are watching for some file to be created, to read it in, watch for CREATE, then watch for CLOSE_WRITE on that same file, and then try to read it, and see if that works better.