I'm trying to develop a service that whenever an user opens an app my service will identify it. I'm using the files: /proc/[pid]/cgroup,/proc/[pid]/cmdline,/proc/[pid]/oom_score,/proc/[pid]/oom_score_adj to check if it's an user app running on foreground. Actually it's working but when I try to open any game the service won't recognize it all the time. (The service only identify the files (oom_score) that has the lowest value).
Example: oom_score for "com.google.android.googlequicksearchbox:interactor" is 75, but for "com.king.candycrushsaga" will be >150, so it will never be detected by the code (as it follows).
Service code:
scheduler.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
s=appManager.getAppRunningForeground();
System.out.println(s);
}
},1,2,SECONDS);
Function that gets the app running:
private ReadWriteFile readWriteFile = new ReadWriteFile();
public String getAppRunningForeground(){
int pid;
File[] files = new File("/proc").listFiles();
int lowestOomScore = Integer.MAX_VALUE;
String foregroundProcess = null;
for (File file : files) {
if (!file.isDirectory() || (!file.getName().matches(("\\d+"))))
continue;
pid = Integer.parseInt(file.getName());
try {
String cgroup = readWriteFile.read(String.format("/proc/%d/cgroup", pid));
String[] lines = cgroup.split("\n");
if (lines.length != 2)
continue;
String cpuSubsystem = lines[0];
String cpuaccctSubsystem = lines[1];
if (!cpuaccctSubsystem.endsWith(Integer.toString(pid)) || cpuSubsystem.endsWith("bg_non_interactive"))
continue;
String cmdline = readWriteFile.read(String.format("/proc/%d/cmdline", pid));
if (cmdline.contains("com.android.systemui")||cmdline.contains("com.google.android.googlequicksearchbox:interactor")) {
continue;
}
int uid = Integer.parseInt(cpuaccctSubsystem.split(":")[2].split("/")[1].replace("uid_", ""));
if (uid > 1000 && uid <= 1038)//System process
continue;
File oomScoreAdj = new File(String.format("/proc/%d/oom_score_adj", pid));
if (oomScoreAdj.canRead()) {
int oomAdj = Integer.parseInt(readWriteFile.read(oomScoreAdj.getAbsolutePath()));
if (oomAdj != 0) {
continue;
}
}
int oomscore = Integer.parseInt(readWriteFile.read(String.format("/proc/%d/oom_score", pid)));
if (oomscore < lowestOomScore) {
lowestOomScore = oomscore;
foregroundProcess = cmdline.replaceAll("\\p{Cntrl}", "");
}
} catch (IOException e) {
e.printStackTrace();
}
}
return foregroundProcess;
}
Class that reads a file.
public class ReadWriteFile{
File file;
StringBuilder teste3 = new StringBuilder();
FileOutputStream outputStream;
public static String read(String path) throws IOException {
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(new FileReader(path));
output.append(reader.readLine());
for (String line = reader.readLine(); line != null; line = reader.readLine())
output.append('\n').append(line);
reader.close();
return output.toString();
}
}
P.S: getRunningTasks is deprecated, so please, don't suggest it.
You can use UsageStatsManager class added in android api 21. See this
question raised and answered by me.
The above answer will provide you an sorted applications ArrayList, required foreground application will the first one in the ArrayList on the index number 0.
Hope this will help.
This methods help you
void checkForegroundAppCompat()
{
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final List<ActivityManager.RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1);
final ComponentName componentName = taskInfo.get(0).topActivity;
if(!getWhiteListedPackages().contains(componentName.getPackageName()) &&
SecurityStatusManager.isAppsBlockingEnabled(this))
{
int pid = android.os.Process.getUidForName(componentName.getPackageName());
// Kill blick APP here
GRLog.w("KILL Blacklist App Package: " + componentName.getPackageName() + " with pid: " + pid);
killApp(componentName.getPackageName(), pid);
}
}
Related
I am trying to check whether device having external storage or not by using external storage path like this given below
if (new File("/ext_card/").exists()) {
specialPath = "/ext_card/";
} else if (new File("/mnt/sdcard/external_sd/").exists()) {
specialPath = "/mnt/sdcard/external_sd/";
} else if (new File("/storage/extSdCard/").exists()) {
specialPath = "/storage/extSdCard/";
} else if (new File("/mnt/extSdCard/").exists()) {
specialPath = "/mnt/extSdCard/";
} else if (new File("/mnt/sdcard/external_sd/").exists()) {
specialPath = "/mnt/sdcard/external_sd/";
} else if (new File("storage/sdcard1/").exists()) {
specialPath = "storage/sdcard1/";
}
But in marshmallow I con't find this path and while checking using ES FILEMANAGER, they give like storage/3263-3131 in Moto G 3rd generation. While check in other marshmallow devices that numbers getting differ. Please help me to check that marshmallow device have external storage or not? and if storage found means how to get the path of that external storage?
Note:- I gave permission for storage in my application and also enabled storage permission in settings for my app.
Thanks in advance and did you find any mistake in my question please crt it. thank you again.
Here's my solution, which is guaranteed to work till Android 7.0 Nougat:
/* returns external storage paths (directory of external memory card) as array of Strings */
public String[] getExternalStorageDirectories() {
List<String> results = new ArrayList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //Method 1 for KitKat & above
File[] externalDirs = getExternalFilesDirs(null);
String internalRoot = Environment.getExternalStorageDirectory().getAbsolutePath().toLowerCase();
for (File file : externalDirs) {
if(file==null) //solved NPE on some Lollipop devices
continue;
String path = file.getPath().split("/Android")[0];
if(path.toLowerCase().startsWith(internalRoot))
continue;
boolean addPath = false;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
addPath = Environment.isExternalStorageRemovable(file);
}
else{
addPath = Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(file));
}
if(addPath){
results.add(path);
}
}
}
if(results.isEmpty()) { //Method 2 for all versions
// better variation of: http://stackoverflow.com/a/40123073/5002496
String output = "";
try {
final Process process = new ProcessBuilder().command("mount | grep /dev/block/vold")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
output = output + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
if(!output.trim().isEmpty()) {
String devicePoints[] = output.split("\n");
for(String voldPoint: devicePoints) {
results.add(voldPoint.split(" ")[2]);
}
}
}
//Below few lines is to remove paths which may not be external memory card, like OTG (feel free to comment them out)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int i = 0; i < results.size(); i++) {
if (!results.get(i).toLowerCase().matches(".*[0-9a-f]{4}[-][0-9a-f]{4}")) {
Log.d(LOG_TAG, results.get(i) + " might not be extSDcard");
results.remove(i--);
}
}
} else {
for (int i = 0; i < results.size(); i++) {
if (!results.get(i).toLowerCase().contains("ext") && !results.get(i).toLowerCase().contains("sdcard")) {
Log.d(LOG_TAG, results.get(i)+" might not be extSDcard");
results.remove(i--);
}
}
}
String[] storageDirectories = new String[results.size()];
for(int i=0; i<results.size(); ++i) storageDirectories[i] = results.get(i);
return storageDirectories;
}
I found the solution for this over here https://stackoverflow.com/a/13648873/842607
The code is -
public static HashSet<String> getExternalMounts() {
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try {
final Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines) {
if (!line.toLowerCase(Locale.US).contains("asec")) {
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!part.toLowerCase(Locale.US).contains("vold"))
out.add(part);
}
}
}
}
return out;
}
The other one is the hack which I found from the same page -
private static final Pattern DIR_SEPORATOR = Pattern.compile("/");
/**
* Raturns all available SD-Cards in the system (include emulated)
*
* Warning: Hack! Based on Android source code of version 4.3 (API 18)
* Because there is no standart way to get it.
* TODO: Test on future Android versions 4.4+
*
* #return paths to all available SD-Cards in the system (include emulated)
*/
public static String[] getStorageDirectories()
{
// Final set of paths
final Set<String> rv = new HashSet<String>();
// Primary physical SD-CARD (not emulated)
final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE");
// All Secondary SD-CARDs (all exclude primary) separated by ":"
final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
// Primary emulated SD-CARD
final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET");
if(TextUtils.isEmpty(rawEmulatedStorageTarget))
{
// Device has physical external storage; use plain paths.
if(TextUtils.isEmpty(rawExternalStorage))
{
// EXTERNAL_STORAGE undefined; falling back to default.
rv.add("/storage/sdcard0");
}
else
{
rv.add(rawExternalStorage);
}
}
else
{
// Device has emulated storage; external storage paths should have
// userId burned into them.
final String rawUserId;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
{
rawUserId = "";
}
else
{
final String path = Environment.getExternalStorageDirectory().getAbsolutePath();
final String[] folders = DIR_SEPORATOR.split(path);
final String lastFolder = folders[folders.length - 1];
boolean isDigit = false;
try
{
Integer.valueOf(lastFolder);
isDigit = true;
}
catch(NumberFormatException ignored)
{
}
rawUserId = isDigit ? lastFolder : "";
}
// /storage/emulated/0[1,2,...]
if(TextUtils.isEmpty(rawUserId))
{
rv.add(rawEmulatedStorageTarget);
}
else
{
rv.add(rawEmulatedStorageTarget + File.separator + rawUserId);
}
}
// Add all secondary storages
if(!TextUtils.isEmpty(rawSecondaryStoragesStr))
{
// All Secondary SD-CARDs splited into array
final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
Collections.addAll(rv, rawSecondaryStorages);
}
return rv.toArray(new String[rv.size()]);
}
This library solve my problem.
https://github.com/hendrawd/StorageUtil
What i did is:
private File directory;
String[] allPath;
allPath = StorageUtil.getStorageDirectories(this);
for (String path: allPath){
directory = new File(path);
Methods.update_Directory_Files(directory);
}
Methods.update_Directory_Files()
// Retrieving files from memory
public static void update_Directory_Files(File directory) {
//Get all file in storage
File[] fileList = directory.listFiles();
//check storage is empty or not
if(fileList != null && fileList.length > 0)
{
for (int i=0; i<fileList.length; i++)
{
boolean restricted_directory = false;
//check file is directory or other file
if(fileList[i].isDirectory())
{
for (String path : Constant.removePath){
if (path.equals(fileList[i].getPath())) {
restricted_directory = true;
break;
}
}
if (!restricted_directory)
update_Directory_Files(fileList[i]);
}
else
{
String name = fileList[i].getName().toLowerCase();
for (String ext : Constant.videoExtensions){
//Check the type of file
if(name.endsWith(ext))
{
//first getVideoDuration
String videoDuration = Methods.getVideoDuration(fileList[i]);
long playbackPosition;
long percentage = C.TIME_UNSET;
FilesInfo.fileState state;
/*First check video already played or not. If not then state is NEW
* else load playback position and calculate percentage of it and assign it*/
//check it if already exist or not if yes then start from there else start from start position
int existIndex = -1;
for (int j = 0; j < Constant.filesPlaybackHistory.size(); j++) {
String fListName = fileList[i].getName();
String fPlaybackHisName = Constant.filesPlaybackHistory.get(j).getFileName();
if (fListName.equals(fPlaybackHisName)) {
existIndex = j;
break;
}
}
try {
if (existIndex != -1) {
//if true that means file is not new
state = FilesInfo.fileState.NOT_NEW;
//set playbackPercentage not playbackPosition
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(fileList[i].getPath());
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
retriever.release();
int duration = Integer.parseInt(time);
playbackPosition = Constant.filesPlaybackHistory.get(existIndex).getPlaybackPosition();
if (duration > 0)
percentage = 1000L * playbackPosition / duration;
else
percentage = C.TIME_UNSET;
}
else
state = FilesInfo.fileState.NEW;
//playbackPosition have value in percentage
Constant.allMemoryVideoList.add(new FilesInfo(fileList[i],
directory,videoDuration, state, percentage));
//directory portion
currentDirectory = directory.getPath();
unique_directory = true;
for(int j=0; j<directoryList.size(); j++)
{
if((directoryList.get(j).toString()).equals(currentDirectory)){
unique_directory = false;
}
}
if(unique_directory){
directoryList.add(directory);
}
//When we found extension from videoExtension array we will break it.
break;
}catch (Exception e){
e.printStackTrace();
Constant.allMemoryVideoList.add(new FilesInfo(fileList[i],
directory,videoDuration, FilesInfo.fileState.NOT_NEW, C.TIME_UNSET));
}
}
}
}
}
}
Constant.directoryList = directoryList;
}
in this i have redmi note prime 2.and i have no memory card.so when i found path and File[] externalDirs = getExternalFilesDirs(null); give null second postion value of file[].
}
I'm developing an app which consists on different tests and for each test (activity) it is needes to read a different txt file. I know doing this but changing it manually. How could be possible to read the proper txt when an specific activity is running. For example for activity 1 I need to read 1.txt and so on.
Here is the code where i read the txts.
String questionFile = "";
questionFile = "1.txt";
questionCount = 20;
Log.i("Question", questionFile + ": " + questionCount);
try {
InputStream is = context.getAssets().open(questionFile);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
// Skips lines
for (i = 0; i< questionNumber; i++) {
reader.readLine();
}
question = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
you will need to put current code inside separate class and create a method for reading file from Assets depend on Activity currently running as:
public class GetFileAssets {
Context context;
public GetFileAssets(Context context){
this.context=context;
}
public String readFilefromAssets(String str_file_id){
String questionFile = "";
questionFile = str_file_id;
questionCount = 20;
//... your code here
return question;
}
}
and now pass file accoding to Activity .like from Actiivty 1:
GetFileAssets obj=new GetFileAssets(Activity1.this);
String str=obj.readFilefromAssets("1.txt");
same from Activity 2 :
GetFileAssets obj=new GetFileAssets(Activity2.this);
String str=obj.readFilefromAssets("2.txt");
I want to know the exact functionality of Intent.ACTION_PRE_BOOT_COMPLETED. Currently, my requirement is to complete the task before the completion of booting of the device, i.e. before the call of Intent.ACTION_BOOT_COMPLETED.
Can anyone guide me on how to proceed to fulfill the requirement? Any help in this regard will be well appreciated.
ACTION_PRE_BOOT_COMPLETED is sended in ActivityManagerService.java::systemReady.
But to received it, the uid of your application must be system(1000).
for (int i=ris.size()-1; i>=0; i--) {
if ((ris.get(i).activityInfo.applicationInfo.flags
&ApplicationInfo.FLAG_SYSTEM) == 0) {
ris.remove(i);
}
}
Further more, this broadcast could only be received once in each upgrade( not very sure here, maybe should be each wipe data).
Note code below, if the target is in lastDoneReceivers, it will be removed.
ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
for (int i=0; i<ris.size(); i++) {
ActivityInfo ai = ris.get(i).activityInfo;
ComponentName comp = new ComponentName(ai.packageName, ai.name);
if (lastDoneReceivers.contains(comp)) {
ris.remove(i);
i--;
}
}
lastDoneReceivers is read from file /data/system/called_pre_boots.dat.
private static File getCalledPreBootReceiversFile() {
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
File fname = new File(systemDir, "called_pre_boots.dat");
return fname;
}
static final int LAST_DONE_VERSION = 10000;
private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
File file = getCalledPreBootReceiversFile();
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
int fvers = dis.readInt();
if (fvers == LAST_DONE_VERSION) {
String vers = dis.readUTF();
String codename = dis.readUTF();
String build = dis.readUTF();
if (android.os.Build.VERSION.RELEASE.equals(vers)
&& android.os.Build.VERSION.CODENAME.equals(codename)
&& android.os.Build.VERSION.INCREMENTAL.equals(build)) {
int num = dis.readInt();
while (num > 0) {
num--;
String pkg = dis.readUTF();
String cls = dis.readUTF();
lastDoneReceivers.add(new ComponentName(pkg, cls));
}
}
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
return lastDoneReceivers;
}
There is no such action as ACTION_PRE_BOOT_COMPLETED. I think that you normally can't fill your requirement. May be there is some mechanism for system signed apps to do that.
I am having an issue while parsing a CSV file. It is only 2 rows of data with a comma separating them. Row one is a date and row 2 is a value. The date field will always have dates in it but sometimes the value is blank (or null?). When it gets to the null value I get a StringIndexOutOfBoundsException and the app crashes. I am logging each loop and can see the data but as soon as I get to a null value it stops looping and gives the error. If there are no null values then it works perfect. Here is my code:
BufferedReader buf = new BufferedReader(new StringReader(file));
String line = null;
while ((line = buf.readLine()) != null) {
try {
String date = null, value = null;
String[] RowData = line.split(",");
date = RowData[0];
value = RowData[1]; (this is the row it crashes on)
This is what the CSV looks like:
2011-08-28 09:16,8.23
2011-08-28 09:15,8.24
2011-08-28 09:14,8.26
2011-08-28 09:13,8.34
2011-08-28 09:12,
2011-08-28 09:11,10.72
2011-08-28 09:10,
2011-08-28 09:09,
the value at 09:13 is the last thing in logcat before I get the error.
This fixed it:
if(RowData.length == 2) {
date = RowData[0];
value = RowData[1];
} else {
date = RowData[0];
value = "0";
}
I wrote a 0 in the value field so later processes will not choke on the null value. Thanks for all your help guys!
You want to do this or something like it:
String date = null, value = null;
String[] RowData = line.split(",");
date = RowData[0];
if(RowData.length ==2)value = RowData[1]; (this is the row it crashes on)
Or some variation of it e.g. if(RowData.length < 2) dont attempt to read the value. Its a pretty standard thing - if you ask an array for an index of a value it doesn't have Java will crash.
Why write your own CSV parsing when you could use a library that has already been written which will do it for you? Perhaps OpenCSV would help you achieve your CSV parsing goal.
Check the length of RowData before you try to access it. It looks like split() is returning an array with a single object but you're trying to access the second object, which is indeed out of bounds.
public class CityParser {
DocumentBuilderFactory factory;
DocumentBuilder builder;
Document doc;
Element ele;
int mediaThumbnailCount;`enter code here`
boolean urlflag;
CityListBean objBean = null;
Vector<CityListBean> vecCityList;
public CityParser() {
}
public Vector<CityListBean> getCityData() {
vecCityList = new Vector<CityListBean>();
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet(
"http://heresmyparty.com/cms/index.php?option=com_chronocontact&chronoformname=add_event_form_download");
HttpResponse response = httpClient.execute(httpGet, localContext);
// String result = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
CSVReader csvreader = new CSVReader(reader);
String[] nextLine;
while ((nextLine = csvreader.readNext()) != null) {
CityListBean objcitylist = new CityListBean();
// nextLine[] is an array of values from the line
objcitylist.setText_title(nextLine[5]);
objcitylist.setText_host(nextLine[6]);
objcitylist.setText_price(nextLine[7]);
objcitylist.setDate(nextLine[8]);
objcitylist.setText_venue(nextLine[11]);
objcitylist.setAddress(nextLine[12]);
objcitylist.setLatitude(nextLine[13]);
objcitylist.setLongitude(nextLine[14]);
objcitylist.setFile(nextLine[15]);
objcitylist.setText_description(nextLine[16]);
objcitylist.setCity(nextLine[17]);
vecCityList.addElement(objcitylist);
}
/*for (int i = 0; i < vecCityList.size(); i++) { CityListBean
objcity = (CityListBean) vecCityList.get(i);
System.out.println("Cf_id : " + objcity.getCityName());
System.out.println("-----------------------------------"); }*/
} catch (Exception ex) {
ex.printStackTrace();
}
return vecCityList;
}
}
==========================================================================================
public class CSVReader {
private BufferedReader br;
private boolean hasNext = true;
private char separator;
private char quotechar;
private int skipLines;
private boolean linesSkiped;
public static final char DEFAULT_SEPARATOR = ',';
public static final char DEFAULT_QUOTE_CHARACTER = '"';
public static final int DEFAULT_SKIP_LINES = 0;
public CSVReader(Reader reader) {
this(reader, DEFAULT_SEPARATOR, DEFAULT_QUOTE_CHARACTER,
DEFAULT_SKIP_LINES);
}
public CSVReader(Reader reader, char separator, char quotechar, int line) {
this.br = new BufferedReader(reader);
this.separator = separator;
this.quotechar = quotechar;
this.skipLines = line;
}
public String[] readNext() throws IOException {
String nextLine = getNextLine();
return hasNext ? parseLine(nextLine) : null;
}
private String getNextLine() throws IOException {
if (!this.linesSkiped) {
for (int i = 0; i < skipLines; i++) {
br.readLine();
}
this.linesSkiped = true;
}
String nextLine = br.readLine();
if (nextLine == null) {
hasNext = false;
}
return hasNext ? nextLine : null;
}
private String[] parseLine(String nextLine) throws IOException {
if (nextLine == null) {
return null;
}
List<String> tokensOnThisLine = new ArrayList<String>();
StringBuffer sb = new StringBuffer();
boolean inQuotes = false;
do {
if (inQuotes) {
// continuing a quoted section, reappend newline
sb.append("\n");
nextLine = getNextLine();
if (nextLine == null)
break;
}
for (int i = 0; i < nextLine.length(); i++) {
char c = nextLine.charAt(i);
if (c == quotechar) {
// this gets complex... the quote may end a quoted block, or escape another quote.
// do a 1-char lookahead:
if( inQuotes // we are in quotes, therefore there can be escaped quotes in here.
&& nextLine.length() > (i+1) // there is indeed another character to check.
&& nextLine.charAt(i+1) == quotechar ){ // ..and that char. is a quote also.
// we have two quote chars in a row == one quote char, so consume them both and
// put one on the token. we do *not* exit the quoted text.
sb.append(nextLine.charAt(i+1));
i++;
}else{
inQuotes = !inQuotes;
// the tricky case of an embedded quote in the middle: a,bc"d"ef,g
if(i>2 //not on the begining of the line
&& nextLine.charAt(i-1) != this.separator //not at the begining of an escape sequence
&& nextLine.length()>(i+1) &&
nextLine.charAt(i+1) != this.separator //not at the end of an escape sequence
){
sb.append(c);
}
}
} else if (c == separator && !inQuotes) {
tokensOnThisLine.add(sb.toString());
sb = new StringBuffer(); // start work on next token
} else {
sb.append(c);
}
}
} while (inQuotes);
tokensOnThisLine.add(sb.toString());
return (String[]) tokensOnThisLine.toArray(new String[0]);
}
public void close() throws IOException{
br.close();
}
}
Have you tried to check first
if (RowData[1]!=null) or possibly if (RowData[1]!="")
I don't see why that would cause your app to crash though,
it should just set value to null or ""
I was able to extract main logs from Android application by using the following code:
String[] LOGCAT_CMD = new String[] {
"logcat",
"-d",
"MyApplication:E",
"*:S"};
Process logcatProc = null;
try {
logcatProc = Runtime.getRuntime().exec(LOGCAT_CMD);
} catch (IOException e) {
e.printStackTrace();
return "";
}
String lineSeparator = System.getProperty("line.separator");
StringBuilder strOutput = new StringBuilder();
try {
InputStream ireader = logcatProc.getInputStream();
int temp;
while ( (temp = ireader.read()) != -1 ){
while ( temp != 64 ){
strOutput.append( (char) temp);
temp = ireader.read();
}
strOutput.append(lineSeparator);
line = strOutput.toString();
writeLine(line);
strOutput = new StringBuilder();
}
However, when I try to use the same method to extract event logs, it does not work. I have no idea what the problem is, but when I change LOGCAT_CMD to the following and run the application, ireader.read() returns -1 right away and finishes.
String[] LOGCAT_CMD = new String[] {
"logcat",
"-b",
"events",
"-d",
"[1]:I",
"*:S"
};
Could somebody please help me?
Check out this code. In particular look at collectAndSendLog() in SendLogActivity.java.