I have an app which is autostarting via BroadcastReceiver and is set as a homescreen on Android 2.3.3. API10 on an HTC Desire HD.
The app should play a video repeatedly right after starting, but as the sdcard is not ready it kills the application with a force close error message which doesn't go away.
At least I think it is because of the sdcard.
In the background, the homescreen restarts but the error message doesn't go away, it would be no problem if it would disappear a few seconds later, but it would be even greater if it wouldn't appear at all..
can you help me?
thanks!
edit #1:
this checks if the sdcard is ready. i only need read access..
static public boolean hasStorage(boolean requireWriteAccess) {
String state = Environment.getExternalStorageState();
Log.v("tomi", "storage state is " + state);
if (Environment.MEDIA_MOUNTED.equals(state)) {
if (requireWriteAccess) {
boolean writable = checkFsWritable();
Log.v("tomi", "storage writable is " + writable);
return writable;
} else {
return true;
}
} else if (!requireWriteAccess && Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
do you have a solution for this?
First, you should not need both "autostarting via BroadcastReceiver" and "set as a homescreen". One should suffice, preferably the latter.
Once the activity launches, it can check Environment to see if external storage is ready. If not, it can register a receiver for ACTION_MEDIA_MOUNTED to find out when external storage becomes ready. Once it is ready -- and only at that point -- it can try to play the video.
Related
I have an android app. I have a few users who have a recurring problem: When the app shuts down, every file the app saved is gone. Every folder created is gone. Everything is completely wiped back to square one.
I am carefully saving the game data during every transition and game event, so I am very confident that this is not a case of the user crashing out before the data can be written. Somehow, the data that IS being written but then it's just not persisting after the app is removed from memory.
So-- has anyone had this situation and solved it? The only thing I can imagine is that there's some kind of "filesystem.commit" command I need to call after writing the files, but I can't find that documented anywhere.
Please help!
(Edit) I'm using native code to read and write files. The code I use to write a file is this:
bool WriteFile(char *theFilename, char *theDataPtr, int theLen)
{
FILE* aFile=fopen(theFilename,"w+");
if(!aFile) {Alert("unable to create file %s with error %d", theFilename, errno);return false;}
if(aFile) fclose(aFile);
aFile=fopen(theFilename,"w+b");
if(!aFile) {Alert ("unable to open file %s", theFilename);return false;}
if (aFile)
{
fwrite(theDataPtr, 1, theLen,aFile);
fclose(aFile);
return true;
}
return false;
}
Note:No customers are reporting any alert popups, which are just normal Android message boxes. Also note that this code works on almost every other system-- there's just a few customers that get the wiped data, so I was wondering if it's some weird security or some extra step I need to do to be 100% compatible with all systems.
(Edit) One more piece of information... this is the Java code I use to get the storage path for the app... all files that I try to write are put in this folder.
private void SetFilePath()
{
String storagePath = getFilesDir().getAbsolutePath();
// SDCARD
try {
String storageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(storageState))
storagePath = getExternalFilesDir(null).getAbsolutePath();
} catch (Exception e) {
Log.v(IDS.LOG,
"No permission to access external storage, missing android.permission.WRITE_EXTERNAL_STORAGE");
}
SetFilePathNative(storagePath); // Tells the native code the path
mStorageDir = storagePath;
}
I'm trying to write a continuous stream of data to android wear locally on the wear device. I've a class called DataSaver that works perfectly fine on the phone side, but the same code would not work on the wear device. I've android permission for write, and read on both wear and mobile.
In the constructor for DataSaver, I've the following:
if (!isExternalStorageWritable()) Log.e(TAG, "External storage is not writable"); //This line does not show anything on the log. So, esExternalStorageWritable returns false.
File rootDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);//Environment.getExternalStorageDirectory();
if (!rootDir.canWrite())
{
Log.d(TAG, "cannot write in the root: "+rootDir.toString()+", space: "+rootDir.getUsableSpace()+", can read: "+rootDir.canRead()+", list: "+rootDir.list());
}
Function isExternalStorageWritable() is implemented as follows:
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable()
{
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state))
{
return true;
}
return false;
}
This always goes inside the if statement where I'm checking if rootDir can write. The rootDir.canRead also returns false. The free space on the device is returned as 2.2GB.
The mkdirs in later lines after that fails because it cannot write to root. Any ideas, suggestions? I would greatly appreciate it.
The problem was I had to manually give permission in settings on the watch for it to work. Basically go to: Settings -> Permissions -> Your app, and check if storage is disabled (it was in my case). Click once to toggle the value.
Remember to have write permission on manifest.
I'm trying to play music from a ListView (which takes data from a file path). But everytime i click, it gets an error like this:
09-14 09:58:42.996 1229-1276/? W/AudioTrack﹕ AUDIO_OUTPUT_FLAG_FAST denied by client
Even I use file path directly, it still doesn't work.
Here is my code:
private MediaPlayer mMediaPlayer;
private File dir = new File(Environment.getExternalStorageDirectory() + "/MyOwnMusicFolder");
private File[] files;
public void playSong(int position){ //position of the item in the ListView
if(mMediaPlayer !=null) {
if(mMediaPlayer.isPlaying()){
mMediaPlayer.pause();
}
try {
mMediaPlayer.setDataSource(dir + File.separator + files[position].getName());
mMediaPlayer.prepare();
mMediaPlayer.start();
}
catch (IOException e){
//something...
}
}
}
Edit: I'm using Android Studio + Android Studio Emulator
Edit 2: my mp3 files are completely normal
"Most likely, the tap sound got a AUDIO_OUTPUT_FLAG_FAST in order to use low-latency playback if possible, but the AudioTrack class considered the track settings to be incompatible with the low-latency audio output, so the flag got removed and the track got treated as if the flag hadn't been set to begin with. So I wouldn't consider this to be something to worry about.
As for the reason why the flag got denied; I'd still say that the most probable reason is a sample rate mismatch. The log in the question you linked to appears to have been added in this commit to the AOSP. But if we look at the master branch of the code base used on many Qualcomm-based devices we see that it still has the "AUDIO_OUTPUT_FLAG_FAST denied by client" log in the case were there was a sample rate mismatch. Which logs you get depends on the exact implemetation running on your device (i.e. which device and Android version you're running)."
Answer was taken from here. Credits to Michael
This most like is caused by mismatch on the sample rate and it should not affect the program runtime IF it is running on an actual device. Ref:
My android application will be preinstalled. And I want to keep tracking of preinstalled apps.
For this purpose I need somehow to save a key or a flag (which means that app is preinstalled). I will add this key to each request to my back-end and will analyze it.
I have an issue with that. An issue is about update from Google Play.
The standart workflow is the following:
1) I give to a manufacturer a special version of my application, which saves a key somehow (in Shared Prefs for example).
2) Manufacturer sell device with the app (special, modified).
3) When User get it, there definetly be next version of the app (standart, without special code) in the Google Play, so user perhaps update it without any launching (the worst case).
4) I lost my tracking possibility. (new apk fully removing never launched old one which was special)
To solve it I was listening a system broadcast ON_BOOT_COMPLETE, but its not working properly on Android 3.1+.
Have you any ideas how can I do that?
Can you install an additional .apk that only has a service? Then that service can have the key, etc. and it can listen for when your app starts and send the tracking info. Then it won't matter if your app gets upgraded; the service will still be the same.
There are some ways to know if application is system application or not. Like by checking installed directory of application or check FLAG_SYSTEM for the application.
Method 1 : -
Check location of application
public static boolean applicationIsSystemApp(Context mContext, String packageName) {
try {
ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
String appLocation = applicationInfo.publicSourceDir;
// OR String appLocation = applicationInfo.sourceDir;
// Both returns the same
// if package is pre-installed then output will be /system/app/application_name.apk
// if package is installed by user then output will be /data/app/application_name.apk
// Check if package is system app
if (appLocation != null && appLocation.startsWith("/system/app/")) {
return true;
}
} catch (NameNotFoundException e) {
e.printStackTrace(); // TODO Can handle as your logic
}
return false;
}
Method 2 : -
Check FLAG_SYSTEM of application
public static boolean applicationIsSystemApp(Context mContext, String packageName) {
try {
ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
// FLAG_SYSTEM is only set to system applications,
// this will work even if application is installed in external storage
// Check if package is system app
if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
return true;
}
} catch (NameNotFoundException e) {
e.printStackTrace(); // TODO Can handle as your logic
}
return false;
}
And call this method as
if (applicationIsSystemApp(getApplicationContext(), "com.example.mysystemapp")) {
// Application is system app
} else {
// Application has been installed as 3rd Party app
}
There is a property sourceDir in ApplicationInfo class. You can use it to distinguish the system app version and the upgraded one.
System app will start with "/system/app" and upgraded app will start with "/data/app"
Try something like this
try {
ApplicationInfo appInfo = this.getPackageManager().getApplicationInfo("com.example.san", 0);
boolean isSystemApp = false;
if(appInfo.sourceDir.startsWith("/system/app")){ // You can use "contains" too
isSystemApp = true;
}
} catch (Exception e) {
e.printStackTrace();
}
Note: I didnt test it.. Hope it works
One proven solution is to pre-install an APK that on have the permission: RECEIVE_BOOT_COMPLETED
Then on the very first boot - you make a quick notation that you are a PREINSTALLED to whatever persistent storage you use, preferably add a token file.
You look for this token file on all your later APK versions to determine if the running copy originates from a device which had it pre-installed or not.
This solves the mayor issues:
1) Then its OK if the user updates you APK to the latest version, you can still read this token.
2) You don't have to maintain a separate APK on google play for the pre-installed community
3) You don't have to hustle with the OEM to install multiple APK when you actually only have one App.
There is an application and it needs system reboot after installation. I registrered boot receiver and write info to system log. And activity checks for this line. It works well, but there is one problem...
When user uninstall and install this app in one session(I mean user doesn't reboot phone) system log still has line "Phone restarted" and application runs with errors.
As I know I can't check uninstallation event on my app cause receiver stops before the application going to uninstall. So my question is could I check for my app installation? or maybe uninstallation any other way?
Thanks!
Maybe someone will be interested. I found the code that allows me to checked system reboot after installation/update:
public static boolean phone_rebooted(Context ctx) {
ApplicationInfo appInfo = ctx.getApplicationInfo();
String appFile = appInfo.sourceDir;
long installed = new File(appFile).lastModified();
long boot_time = System.currentTimeMillis() - SystemClock.elapsedRealtime();
if(boot_time < installed) {
return false;
} else {
return true;
}
}