So in my toolkit, id like to design an activity where I could point it towards certain lines in the build.prop to allow a user to easily toggle, for instance this line
qemu.hw.mainkeys=0
So, in the layout xml, lets say it had "Enable Nav Bar" and a "Toggle Button" for on/off
Where would i start in developing such a feature?
You create a ToggleButton and whenever it is clicked, you change the line.
What is your problem?
nikwen said:
You create a ToggleButton and whenever it is clicked, you change the line.
What is your problem?
Click to expand...
Click to collapse
My concerns are wouldnt I need to add ro permissions on the prop before toggling and a reboot action to apply
I think your device needs to be rooted to be able to write to the build.prop file. You do not need root access to read it though
I'm from mobile and i can't post some code but i will give you some hints
To edit build.prop programmatically first you ne ed to be rooted then you can use the shell command "sed" to exchange values. Take a look at AOKP settings source on github and look for density changer class
If you want to import various build properties you can use fileinputstream and read the file line by line then let the app create listview custom items for every line in the file (you need a custom adapter) .
Sorry if this post it's not really useful but i will edit this when at PC
Sent from my HTC One X using Tapatalk 4 Beta
Thankyou for the tip! The answer might of been infront of my face possibly...
Sent from my 9300 using xda app-developers app
xcesco89 said:
I'm from mobile and i can't post some code but i will give you some hints
To edit build.prop programmatically first you ne ed to be rooted then you can use the shell command "sed" to exchange values. Take a look at AOKP settings source on github and look for density changer class
If you want to import various build properties you can use fileinputstream and read the file line by line then let the app create listview custom items for every line in the file (you need a custom adapter) .
Sorry if this post it's not really useful but i will edit this when at PC
Sent from my HTC One X using Tapatalk 4 Beta
Click to expand...
Click to collapse
I Wrote something up but I keep getting force closes "Not a java code monkey yet, still learning" and Ill post here what I have when I get to my pc later. Maybe you can see what Im missing or did wrong. What I did is I have a preference screen similiar to AOKP density changer class. What Im going for is a PreferenceList that you click and your values are Enable or Disabled and another preference to reboot to apply settings. Im wanting to allow the user to enable and disable the Navigation Bar by toggling it through the build.prop. If this works, I want to add more toggles custom values like change your phone model, Screen Density, build number, ect; but figured Id start with something simpler first and see if it works.
Sent from my Alps9300 using Tapatalk
Nx Biotic said:
I Wrote something up but I keep getting force closes "Not a java code monkey yet, still learning" and Ill post here what I have when I get to my pc later. Maybe you can see what Im missing or did wrong. What I did is I have a preference screen similiar to AOKP density changer class. What Im going for is a PreferenceList that you click and your values are Enable or Disabled and another preference to reboot to apply settings. Im wanting to allow the user to enable and disable the Navigation Bar by toggling it through the build.prop. If this works, I want to add more toggles custom values like change your phone model, Screen Density, build number, ect; but figured Id start with something simpler first and see if it works.
Sent from my Alps9300 using Tapatalk
Click to expand...
Click to collapse
this is the method you need:
Code:
private void setLcdDensity(int newDensity) {
Helpers.getMount("rw");
new CMDProcessor().su.runWaitFor("busybox sed -i 's|ro.sf.lcd_density=.*|"
+ "ro.sf.lcd_density" + "=" + newDensity + "|' " + "/system/build.prop");
Helpers.getMount("ro");
}
( method took from here : https://github.com/TeamBAKED/packag...aked/romcontrol/fragments/DensityChanger.java )
newDensity is the int/string you let the user set ( you can use a seekbar or a dialog or what you prefer)
you have also CMDProcessor().su.runWaitFor : just use the classes you can find here : https://github.com/TeamBAKED/packag...11bca71808c9143/src/com/baked/romcontrol/util
just add these classes in your project ( these are to simplify your life when you need to use android terminal [ remember to give credits on your app! ] )
Now, you can use various types of views and methods to show to the user all the available props:
- manually add every view for every line in your build.prop ( this will probably limit the compatibility with other devices and make your app "laggy" due to "gazilions" views )
- use a blank linearLayout and inflate a "row view" for every line in build.prop:
read file line by line and import every line in an ArrayList:
Code:
ArrayList<String> Tokens = new ArrayList<String>();
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("/system/build.prop");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
strLine = strLine.trim();
if ((strLine.length()!=0)) {
String[] names = strLine.split("\\s+");
Tokens.add(names[0]);
}
}
for (String s : Tokens) {
//System.out.println(s);
//Log.d("NNNNNNNNNNNNNNNNNN", s);
}
// Close the input stream
in.close();
} catch (Exception e) {// Catch exception if any
System.err.println("Error: " + e.getMessage());
}
names = new String[Tokens.size()-1];
names = Tokens.toArray(names);
ArrayList<String> value = new ArrayList<String>();
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("/sys/devices/system/cpu/cpu0/cpufreq/UV_mV_table");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
strLine = strLine.trim();
if ((strLine.length()!=0)) {
String[] val = strLine.split("\\s+");
value.add(val[1]);
}
}
for (String s : value) {
//System.out.println(s);
//Log.d("NNNNNNNNNNNNNNNNNN", s);
}
// Close the input stream
in.close();
} catch (Exception e) {// Catch exception if any
System.err.println("Error: " + e.getMessage());
}
values = new String[value.size()-1];
values = value.toArray(values);
LineNumberReader lnr = null;
try {
lnr = new LineNumberReader(new FileReader(new File("/sys/devices/system/cpu/cpu0/cpufreq/UV_mV_table")));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
lnr.skip(Long.MAX_VALUE);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int num = lnr.getLineNumber();
Log.d("LINES", ""+num);
int i = 0;
//now inflate a specific view for every line
// you can also filter every item for example by reading the string and inflating a different layout using an if statement
for (String s : names) {
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View v = inflater.inflate(R.layout.uvrow, null, true);
TextView text0 = (TextView) v.findViewById(R.id.text0);
ImageButton back0 = (ImageButton) v.findViewById(R.id.back0);
final EditText edit0 = (EditText) v.findViewById(R.id.edit0);
ImageButton fwd0 = (ImageButton) v.findViewById(R.id.fwd0);
text0.setText(s);
parentGroup.addView(v);
edit0.setText(values[i]);
/*
* if you need to set listeners and actions insert them inside this loop!
*/
}
if you need more informations, take a look at my code on github ( was my first "really useful" app ): https://github.com/cesco89/CustomSettings/blob/master/src/com/cesco/customsettings/UVTable.java
it's not perfect, could be tricky, but i can't post all the code here
This Is what I put together...Excuse any errors in java...Im new at this. When I start this fragment, I get a force close. What did I do?
Code:
package com.bionx.res.catalyst;
import android.content.Context;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
import com.bionx.res.R;
import com.bionx.res.helpers.CMDProcessor;
import com.bionx.res.helpers.Helpers;
public abstract class Navbar extends PreferenceFragment implements OnPreferenceChangeListener {
Preference mReboot;
ListPreference mStockValue;
int newStockValue;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.navbarchanger);
mStockValue = (ListPreference) findPreference("stock_value");
mStockValue.setOnPreferenceChangeListener(this);
mReboot = findPreference("reboot");
}
public boolean onPreference(Preference preference) {
if (preference == mReboot) {
PowerManager pm = (PowerManager) getActivity()
.getSystemService(Context.POWER_SERVICE);
pm.reboot("Setting Navbar");
}
return false;
}
[user=439709]@override[/user]
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mStockValue) {
newStockValue = Integer.parseInt((String) newValue);
setNavbarValue(newStockValue);
mStockValue.setSummary(getResources().getString(R.string.navbar_changer) + newStockValue);
return true;
}
return false;
}
private void setNavbarValue(int newNavbar) {
Helpers.getMount("rw");
new CMDProcessor().su.runWaitFor("busybox sed -i 's|qemu.hw.mainkeys=.*|"
+ "qemu.hw.mainkeys" + "=" + newNavbar + "|' " + "/system/build.prop");
Helpers.getMount("ro");
}
}
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="System Properties"
android:summary="User System Tweaks" />
<ListPreference
android:entries="@array/navbar_stock_entries"
android:entryValues="@array/navbar_stock_values"
android:key="stock_value"
android:title="NavBar Enabler"
android:summary="Toggle the system navbar" />
<Preference
android:key="reboot"
android:title="Reboot"
android:summary="Applies tweaks and reboots" />
</PreferenceScreen>
Where I launch the fragment.
Code:
...
<header
android:fragment="com.bionx.res.catalyst.Navbar"
android:icon="@drawable/ic_changelog"
android:title="System Ui Tweaks"
android:summary="Developers soup of the week" />
...
Nx Biotic said:
This Is what I put together...Excuse any errors in java...Im new at this. When I start this fragment, I get a force close. What did I do?
Code:
package com.bionx.res.catalyst;
import android.content.Context;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
import com.bionx.res.R;
import com.bionx.res.helpers.CMDProcessor;
import com.bionx.res.helpers.Helpers;
public abstract class Navbar extends PreferenceFragment implements OnPreferenceChangeListener {
Preference mReboot;
ListPreference mStockValue;
int newStockValue;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.navbarchanger);
mStockValue = (ListPreference) findPreference("stock_value");
mStockValue.setOnPreferenceChangeListener(this);
mReboot = findPreference("reboot");
}
public boolean onPreference(Preference preference) {
if (preference == mReboot) {
PowerManager pm = (PowerManager) getActivity()
.getSystemService(Context.POWER_SERVICE);
pm.reboot("Setting Navbar");
}
return false;
}
[user=439709]@override[/user]
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mStockValue) {
newStockValue = Integer.parseInt((String) newValue);
setNavbarValue(newStockValue);
mStockValue.setSummary(getResources().getString(R.string.navbar_changer) + newStockValue);
return true;
}
return false;
}
private void setNavbarValue(int newNavbar) {
Helpers.getMount("rw");
new CMDProcessor().su.runWaitFor("busybox sed -i 's|qemu.hw.mainkeys=.*|"
+ "qemu.hw.mainkeys" + "=" + newNavbar + "|' " + "/system/build.prop");
Helpers.getMount("ro");
}
}
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="System Properties"
android:summary="User System Tweaks" />
<ListPreference
android:entries="@array/navbar_stock_entries"
android:entryValues="@array/navbar_stock_values"
android:key="stock_value"
android:title="NavBar Enabler"
android:summary="Toggle the system navbar" />
<Preference
android:key="reboot"
android:title="Reboot"
android:summary="Applies tweaks and reboots" />
</PreferenceScreen>
Where I launch the fragment.
Code:
...
<header
android:fragment="com.bionx.res.catalyst.Navbar"
android:icon="@drawable/ic_changelog"
android:title="System Ui Tweaks"
android:summary="Developers soup of the week" />
...
Click to expand...
Click to collapse
please post the Log you get on Eclipse !
the log will tell you exactly where the error is
I'm developing an Android app that purchase errors copying files from /assets to /system. I have this code but I don't know why isn't works. Can anybody help me, This is my code:
Code:
public class MainActivity extends Activity
{
ProgressDialog progressDialog = null;
/** Called when the activity is first created. */
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
{
}}
public void reparar(View view) throws IOException {
progressDialog = ProgressDialog.show(MainActivity.this, "Instalando parche", "Por favor, espere...", true);
//Aqi poner el conjunto de acciones hasta mover los archivos al
//directorio system
try {
ProcessBuilder pb = new ProcessBuilder(new String[] { "su", "mount -o rw, remount -t yaffs2 /dev/block/mtdblock4 /system", "cp /assets/keypad/file.format /system", "mount -o ro, remount -t yaffs2 /dev/block/mtdblock4 /system" });
java.lang.Process process = pb.start();
process.waitFor();
} catch (IOException e) {
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
progressDialog.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Debe reiniciar el terminal. Desea hacerlo ahora?")
.setTitle("Instalacion satisfactoria!")
.setCancelable(false)
.setNegativeButton("Reiniciar mas tarde",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setPositiveButton("Reiniciar ahora",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// metodo que se debe implementar
try {
ProcessBuilder pb = new ProcessBuilder(new String[] { "su", "-c", "/system/bin/reboot" });
java.lang.Process process = pb.start();
process.waitFor();
} catch (IOException e) {
}
// TODO Auto-generated method stub
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
[user=439709]@override[/user]
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.options, menu);
return true;
}
}
Enviado desde mi GT-S5570I usando Tapatalk 2
Please! Help me :crying:
DannyGM16 said:
Please! Help me :crying:
Click to expand...
Click to collapse
first you'll have to copy the file from the apk-assets folder to /data/data/your.pqackage.name/file/file.format, after that you can copy it as root to the system partition.
Code:
String data_storage_root = mContext.getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/file.format");
if (h.exists()) h.setWritable(true, true);
try {
is = mContext.getResources().getAssets().open("keypad/file.format");
os = new FileOutputStream(data_storage_root+"/file.format");
IOUtils.copy(is, os);
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success copying");
} catch (IOException e) {
Log.w(TAG, "failed copying");
}
h.setExecutable(false, true);
h.setReadable(true, true);
h.setWritable(false, true);
Zatta said:
first you'll have to copy the file from the apk-assets folder to /data/data/your.pqackage.name/file/file.format, after that you can copy it as root to the system partition.
Code:
String data_storage_root = mContext.getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/file.format");
if (h.exists()) h.setWritable(true, true);
try {
is = mContext.getResources().getAssets().open("keypad/file.format");
os = new FileOutputStream(data_storage_root+"/file.format");
IOUtils.copy(is, os);
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success copying");
} catch (IOException e) {
Log.w(TAG, "failed copying");
}
h.setExecutable(false, true);
h.setReadable(true, true);
h.setWritable(false, true);
Click to expand...
Click to collapse
Thanks for the info, I didn't know it!
When I use this code I have two issues, in mContext and IOUtils, what am I doing wrong?
And Copying from data to system I preffer doing it with RootTools. Can u help me pls??
Oh, sorry. This is a snipplet from one of my apps, it uses a library called commons-io-2.1.jar for the IOUtils. The context is just the context from the loader where this snipplet comes from.
I've never used RootUtils so I can't help you with that, sorry.
When I'm not on my phone but at a computer I'll search for an alternative to extract the file from the apk for you (if you haven't found it by then, SO will have an answer for sure).
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Zatta said:
Oh, sorry. This is a snipplet from one of my apps, it uses a library called commons-io-2.1.jar for the IOUtils. The context is just the context from the loader where this snipplet comes from.
I've never used RootUtils so I can't help you with that, sorry.
When I'm not on my phone but at a computer I'll search for an alternative to extract the file from the apk for you (if you haven't found it by then, SO will have an answer for sure).
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Click to expand...
Click to collapse
Lots of thanks! I'm waiting for you
Enviado desde mi GT-S5570I usando Tapatalk 2
Zatta said:
Oh, sorry. This is a snipplet from one of my apps, it uses a library called commons-io-2.1.jar for the IOUtils. The context is just the context from the loader where this snipplet comes from.
I've never used RootUtils so I can't help you with that, sorry.
When I'm not on my phone but at a computer I'll search for an alternative to extract the file from the apk for you (if you haven't found it by then, SO will have an answer for sure).
Taptalked u see .. əəs n tapatalked
Click to expand...
Click to collapse
Code:
import android.app.*;
import android.content.*;
import android.os.*;
import android.os.Process;
import android.util.*;
import android.view.*;
import android.view.View.*;
import android.widget.Button;
import android.widget.Toast;
import java.io.*;
import com.stericson.RootTools.RootTools;
import com.stericson.RootTools.execution.CommandCapture;
import java.util.concurrent.*;
import com.stericson.RootTools.exceptions.*;
import org.apache.commons.io.*;
public class MainActivity extends Activity {
{
}
ProgressDialog progressDialog = null;
/** Called when the activity is first created. */
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (RootTools.isAccessGiven()) {
} else {
makeToast("Se necesitan permisos de Superusuario!");
finish();
}
}
public void reparar(View view) throws IOException, TimeoutException, RootDeniedException, InterruptedException {
CopyFromAssets();
CopyFromAssetstosystem();
End();
}
public void CopyFromAssets() {
progressDialog = ProgressDialog.show(MainActivity.this, "Instalando parche", "Por favor, espere...", true);
String data_storage_root = getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/caca.txt");
File p = new File(data_storage_root+"/caca2.txt");
if (h.exists()) h.setWritable(true, true);
if (p.exists()) h.setWritable(true, true);
try {
is = getResources().getAssets().open("keypad/caca.txt");
is = getResources().getAssets().open("keypad/caca2.txt");
os = new FileOutputStream(data_storage_root+"/sec_key.kl");
os = new FileOutputStream(data_storage_root+"/sec_keypad.kl");
IOUtils.copy(is, os);
is.close();
os.flush();
os.close();
os = null;
} catch (IOException e) {
makeToast("Fallo al copiar");
finish();
}
h.setExecutable(false, true);
h.setReadable(true, true);
h.setWritable(false, true);
}
public void CopyFromAssetstosystem() throws TimeoutException, IOException, RootDeniedException {
CommandCapture command = new CommandCapture(0, "su", "mount -o rw, remount -t yaffs2 /dev/block/mtdblock4 /system", "cp /data/data/com.fixer.gminipop/files/caca.txt /system", "mount -o ro, remount -t yaffs2 /dev/block/mtdblock4 /system");
RootTools.getShell(true).add(command).waitForFinish();
}
public void End() {
ClosePD();
AlertDialog();
}
public void AlertDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Es necesario reiniciar para que se apliquen los cambios. Desea hacerlo ahora?")
.setTitle("Instalacion satisfactoria!")
.setCancelable(false)
.setNegativeButton("Reiniciar mas tarde",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setPositiveButton("Reiniciar ahora",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// metodo que se debe implementar
try {
ProcessBuilder pb = new ProcessBuilder(new String[] { "su", "-c", "/system/bin/reboot" });
java.lang.Process process = pb.start();
process.waitFor();
} catch (IOException e) {
}
// TODO Auto-generated method stub
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
public void ClosePD() {
progressDialog.dismiss();
}
private static void copy(InputStream is, OutputStream os) {
// TODO Auto-generated method stub
}
public void makeToast(String msg) {
Context context = getApplicationContext();
CharSequence text = msg;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
public void RootActions() {
}
}
This is all my code, I use your library and RootTool library.
I have two issues:
1- Error in waitForFinish();
2- processDialog don't appear.
Enviado desde mi GT-S5570I usando Tapatalk 2
Hi,
I've rewrote my snipplet not to use the apache library (eventually it is just one method that was used so this is more clean) and added that to a asynctask.
Better late than never now you have rewritten yours as well :S Attached is the eclipse project.
Also, in your code you are trying to copy two files, that is not going to work like that. You define the inputstream and the outputstream twice. I will make this thing work for you if you haven't figured it out tomorrow, will take 24 hrs for me to come back on this. I don't use roottools as I said but maybe I'll look into that as well. Else I will give you an alternative.
Code:
package by.zatta.copyassets;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = "Copy Example";
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new PlantFiles().execute();
}
private void doneBackground(boolean succes){
// this method should be used to progress further after,
// update the ui, do other things like copying the file to /system
if (succes)
Toast.makeText(this, "Copied!", Toast.LENGTH_LONG).show();
else
Toast.makeText(this, "Failed", Toast.LENGTH_LONG).show();
}
private class PlantFiles extends AsyncTask<Void, Void, Boolean> {
protected Boolean doInBackground(Void... arg0) {
String data_storage_root = getApplicationContext().getFilesDir().toString();
boolean copied=false;
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/file.format");
if (h.exists()) h.delete();
try {
is = getApplicationContext().getResources().getAssets().open("keypad/file.format");
os = new FileOutputStream(data_storage_root+"/file.format");
if (copy(is, os)) copied = true;
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success copying certificate generic");
} catch (IOException e) {
Log.w(TAG, "failed copying certificate generic");
}
return copied;
}
protected void onPostExecute(Boolean result){
doneBackground(result);
}
private boolean copy(InputStream in, OutputStream out){
try {
byte[] buffer = new byte[1024];
int read;
while (( read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
return true;
} catch (IOException e) {
Log.w(TAG, "problems copying");
return false;
}
}
}
}
Zatta said:
Hi,
I've rewrote my snipplet not to use the apache library (eventually it is just one method that was used so this is more clean) and added that to a asynctask.
Better late than never now you have rewritten yours as well :S Attached is the eclipse project.
Also, in your code you are trying to copy two files, that is not going to work like that. You define the inputstream and the outputstream twice. I will make this thing work for you if you haven't figured it out tomorrow, will take 24 hrs for me to come back on this. I don't use roottools as I said but maybe I'll look into that as well. Else I will give you an alternative.
Code:
package by.zatta.copyassets;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = "Copy Example";
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new PlantFiles().execute();
}
private void doneBackground(boolean succes){
// this method should be used to progress further after,
// update the ui, do other things like copying the file to /system
if (succes)
Toast.makeText(this, "Copied!", Toast.LENGTH_LONG).show();
else
Toast.makeText(this, "Failed", Toast.LENGTH_LONG).show();
}
private class PlantFiles extends AsyncTask<Void, Void, Boolean> {
protected Boolean doInBackground(Void... arg0) {
String data_storage_root = getApplicationContext().getFilesDir().toString();
boolean copied=false;
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/file.format");
if (h.exists()) h.delete();
try {
is = getApplicationContext().getResources().getAssets().open("keypad/file.format");
os = new FileOutputStream(data_storage_root+"/file.format");
if (copy(is, os)) copied = true;
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success copying certificate generic");
} catch (IOException e) {
Log.w(TAG, "failed copying certificate generic");
}
return copied;
}
protected void onPostExecute(Boolean result){
doneBackground(result);
}
private boolean copy(InputStream in, OutputStream out){
try {
byte[] buffer = new byte[1024];
int read;
while (( read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
return true;
} catch (IOException e) {
Log.w(TAG, "problems copying");
return false;
}
}
}
}
Click to expand...
Click to collapse
I'm frustrated... You change the name of my functions an now I don't understand anything.
public void reparar is the name of the button function, in your code the functions starts "onCreate".
I prefer my dirty but understable (for me) code
Now I have only one problem, the app works, but it take a long time to reemplace the file in system directory. In other words, I pulse the button, close the application, an in one minute the file is reemplaced. How can I fix that an take this time in a progress dialog?
Sorry for my bad english! I'm spanish
This is my code, is dirty but I think you understand it. Add functions and edit, but no the name of the functions, Please!
Code:
public class MainActivity extends Activity {
ProgressDialog progress;
private static final String TAG = "Copy Example";
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (RootTools.isRootAvailable()) {
} else {
finish();
}
}
public void reparar(View view) throws IOException, TimeoutException, RootDeniedException {
progress = ProgressDialog.show(this, "dialog title",
"dialog message", true);
copyfile1();
copyfile2();
copyfile1tosystem();
copyfile2tosystem();
End();
}
public void copyfile1() {
String data_storage_root = getApplicationContext().getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/sec_key.kl");
if (h.exists()) h.delete();
try {
is = getApplicationContext().getResources().getAssets().open("keypad/sec_key.kl");
os = new FileOutputStream(data_storage_root+"/sec_key.kl");
if (copy(is, os))
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success");
} catch (IOException e) {
Log.w(TAG, "failed copying certificate generic");
}
return;
}
public void copyfile2() {
String data_storage_root = getApplicationContext().getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/sec_keypad.kl");
if (h.exists()) h.delete();
try {
is = getApplicationContext().getResources().getAssets().open("keypad/sec_keypad.kl");
os = new FileOutputStream(data_storage_root+"/sec_keypad.kl");
if (copy(is, os))
is.close();
os.flush();
os.close();
os = null;
} catch (IOException e) {
finish();
}
return;
}
public void copyfile1tosystem() throws IOException, TimeoutException, RootDeniedException {
CommandCapture command = new CommandCapture(0, "su", "mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system", "cp /data/data/com.fixer.gminipop/files/sec_key.kl /system/usr/keylayout/sec_key.kl", "mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system");
RootTools.getShell(true).add(command);
}
public void copyfile2tosystem() throws IOException, TimeoutException, RootDeniedException {
CommandCapture command = new CommandCapture(0, "su", "mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system", "cp /data/data/com.fixer.gminipop/files/sec_keypad.kl /system/usr/keylayout/sec_keypad.kl", "mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system");
RootTools.getShell(true).add(command);
}
public void End() {
progress.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Es necesario reiniciar")
.setTitle("Instalacion satisfactoria!")
.setCancelable(false)
.setNegativeButton("Hacerlo mas tarde",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setPositiveButton("Reiniciar",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// metodo que se debe implementar
try {
ProcessBuilder pb = new ProcessBuilder(new String[] { "su", "-c", "/system/bin/reboot" });
java.lang.Process process = pb.start();
process.waitFor();
} catch (IOException e) {
}
// TODO Auto-generated method stub
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
private boolean copy(InputStream in, OutputStream out){
try {
byte[] buffer = new byte[1024];
int read;
while (( read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
return true;
} catch (IOException e) {
Log.w(TAG, "fallo al copiar");
finish();
return false;
}
}
}
Hi, I haven't had time to produce more code for you.
Just some remarks looking at your code:
1 you duplicate a lot of code
2 your application does everything on the main thread
3 you do a lot of unnescasairy code on the terminal
1)
copyfle 1 and 2 are almost the same, why not use it only once? copyFile(String filename){ ... } for example?
2)
extracting the files form the apk to /data schould be done at the loading of the app, in the background and preferably only once (now it tis done everytime the app starts), then copy it to system at a press of the button. In my example there is a function doneBackground(boolean succes), from there you could set the visiblity of your button to View.VISIBLE, allowing the user to copy the file to /system, now everything is done after the button press.
3)
Code:
"su"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system"
"cp /data/data/com.fixer.gminipop/files/sec_key.kl /system/usr/keylayout/sec_key.kl"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system")
"su"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system"
"cp /data/data/com.fixer.gminipop/files/sec_keypad.kl /system/usr/keylayout/sec_keypad.kl"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system");
this calls 2 times su and it mounts 2 times the system as rw and back to ro, can hugely be optimized
Edit, just read Nikwens reply in your other thread, you don't have to call su at all according to him. However,as I said, I am not a user of Roottools so can't confirm that.
Zatta said:
Hi, I haven't had time to produce more code for you.
Just some remarks looking at your code:
1 you duplicate a lot of code
2 your application does everything on the main thread
3 you do a lot of unnescasairy code on the terminal
1)
copyfle 1 and 2 are almost the same, why not use it only once? copyFile(String filename){ ... } for example?
2)
extracting the files form the apk to /data schould be done at the loading of the app, in the background and preferably only once (now it tis done everytime the app starts), then copy it to system at a press of the button. In my example there is a function doneBackground(boolean succes), from there you could set the visiblity of your button to View.VISIBLE, allowing the user to copy the file to /system, now everything is done after the button press.
3)
Code:
"su"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system"
"cp /data/data/com.fixer.gminipop/files/sec_key.kl /system/usr/keylayout/sec_key.kl"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system")
"su"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system"
"cp /data/data/com.fixer.gminipop/files/sec_keypad.kl /system/usr/keylayout/sec_keypad.kl"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system");
this calls 2 times su and it mounts 2 times the system as rw and back to ro, can hugely be optimized
Edit, just read Nikwens reply in your other thread, you don't have to call su at all according to him. However,as I said, I am not a user of Roottools so can't confirm that.
Click to expand...
Click to collapse
Thank's! I'm going to fix that, Optimice code and clear it. But the problem persist, the copy of the file to system take a long time, and the process to do it is after I close the app, This is my only important error..
Enviado desde mi GT-S5570I usando Tapatalk 2
Ok! I fix all and I'm going to upload it to Google Play, thanks for all your help in this project!
Now I only need your help to put Ads (If my app have lots of downloads) Can u give me a link of a Tutorial?
Enviado desde mi GT-S5570I usando Tapatalk 2
DannyGM16 said:
Ok! I fix all and I'm going to upload it to Google Play, thanks for all your help in this project!
Now I only need your help to put Ads (If my app have lots of downloads) Can u give me a link of a Tutorial?
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
No, I hate ads
Post your play store link here, I'm curious what you made.
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Zatta said:
No, I hate ads
Post your play store link here, I'm curious what you made.
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Click to expand...
Click to collapse
You hate ads and you are a developer? ;D Is the most easy form to win money for your work. I develop apps for fun but I want obtain some money for it You can download my app, but If you don't have a galaxy mini S5570I is useless, only you can watch it...
Enviado desde mi GT-S5570I usando Tapatalk 2
This is my application: https://play.google.com/store/apps/details?id=com.fixer.gminipop
Whatch it in Google Play
Enviado desde mi GT-S5570I usando Tapatalk 2
DannyGM16 said:
This is my application: https://play.google.com/store/apps/details?id=com.fixer.gminipop
Whatch it in Google Play
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
You should get someone to translate all that Spanish to English. I took the effort to translate it for myself (with Google translator) but I'm sure the advantage potential user won't.
Edit, non the less, congratulations with your play store registration!!
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Zatta said:
You should get someone to translate all that Spanish to English. I took the effort to translate it for myself (with Google translator) but I'm sure the advantage potential user won't.
Edit, non the less, congratulations with your play store registration!!
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Click to expand...
Click to collapse
Thank's for show me that error, but I'm going to update it!! Only I have one problem, in one of my update I want to copy a DIRECTORY of assets to /data/data. I watch for the code in a lot o pages, but I don't find it, help me only one more time Pls!
Enviado desde mi GT-S5570I usando Tapatalk 2
Check this for finding translators: http://forum.xda-developers.com/showthread.php?t=2069390
nikwen said:
Check this for finding translators: http://forum.xda-developers.com/showthread.php?t=2069390
Click to expand...
Click to collapse
Nikewn, I know spanish and english, I can translate my app But Thank's. Only I want to resolve my last problem.
DannyGM16 said:
Nikewn, I know spanish and english, I can translate my app But Thank's. Only I want to resolve my last problem.
Click to expand...
Click to collapse
I see that you can write English.
However, you might want to have it translated to other languages, too.
---------- Post added at 03:42 PM ---------- Previous post was at 03:39 PM ----------
DannyGM16 said:
Thank's for show me that error, but I'm going to update it!! Only I have one problem, in one of my update I want to copy a DIRECTORY of assets to /data/data. I watch for the code in a lot o pages, but I don't find it, help me only one more time Pls!
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
Create the directory using the mkdir() method in the java.io.File class. And copy every file to the directory in /data/data. You need to copy the files one by one.
//sorry for my english, if any
Hi. I'm using AIDE right on my device (Xperia NeoV, 4.1.B.0.587, root)
And i'm trying to inject key events through the same shell command:
"input keyevent 25" via "su", both in AIDE Console and separated Activity.
//volume-down key is not my target, just good for tests. I've tried different keys, same result.
Part of the code:
Code:
try {
java.lang.Process p = Runtime.getRuntime().exec("su");
DataOutputStream dos = new DataOutputStream(p.getOutputStream());
dos.writeBytes("input keyevent 25\n");
dos.flush();
} catch (IOException ex) {
//log any errors
}
So, when it goes in AIDE ConsoleApp - it pushes down volume.
But when it executes from my Activity - nothing happens (no error messages in log, dos != null);
Maybe there should be some specific permission on manifest?
"android.permission.ACCESS_SUPERUSER" - no changes.
Maybe there should be some trick in code? Or(and?) i'm very stupid. Also, maybe somewhere a whole listing of _simple_ keyInjection project exists?
I managed to solve it already. I'm using this class now:
public void RunAsRoot(String[] cmds){
Process p = null;
try {
p = Runtime.getRuntime().exec("su");
} catch (IOException e) {
e.printStackTrace();
}
DataOutputStream os = new DataOutputStream(p.getOutputStream());
for (String tmpCmd : cmds) {
try {
os.writeBytes(tmpCmd+"\n");
} catch (IOException e) {
e.printStackTrace();
}
}
try {
os.writeBytes("exit\n");
} catch (IOException e) {
e.printStackTrace();
}
try {
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
Click to expand...
Click to collapse
Then simply call it via
String[] commands = {"command1", "command2", "command3", ...};
RunAsRoot(commands);
Click to expand...
Click to collapse
Thanks anyways!
Click to expand...
Click to collapse
Credits: @KrauseDroid
Our original thread i took it from:
http://forum.xda-developers.com/showthread.php?t=2725173
---------------------------------
Phone : Nexus 4
OS:
Pure KitKat 4.4.2 stock, no root, no mods
---------------------------------
4d 61 73 72 65 70 75 73 20 66 74 77
Gesendet von Tapatalk
Masrepus said:
Credits: @KrauseDroid
Our original thread i took it from:
http://forum.xda-developers.com/showthread.php?t=2725173
Click to expand...
Click to collapse
I saw that thread before creating own, and tried solutions from it. They works same way - only from ConsoleApp in AIDE.
Also, last method is the same as I'm already using, but I've tried to copy code in project - no progress.
In addition:
- superuser rights granted to both.
- test "ls" command put into dos object gives me same list of current dir in both projects, so commands seems to run.
Listing:
MainActivity:
Code:
package com.tsk.mk;
import android.app.*;
import android.content.*;
import android.os.*;
import android.widget.*;
import java.io.*;
public class MainActivity extends Activity {
public static TextView logView;
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
logView = (TextView) findViewById(R.id.log);
log("creating sercice");
final MainActivity me = this;
new Thread() {
[user=439709]@override[/user]
public void run() {
log("thread.run");
startService(new Intent(me, MissedKeysService.class));
log("thread: service shoul'd be created");
}
}.start();
log("end of MA.onCreate method");
}
static void log(String message) {
logView.setText(logView.getText() + "\n" + message);
}
}
MissedKeysService:
Code:
package com.tsk.mk;
import android.app.*;
import android.content.*;
import android.graphics.*;
import android.os.*;
import android.view.*;
import java.io.*;
public class MissedKeysService extends Service {
private WindowManager windowManager;
private MissedKeysView mkv;
private WindowManager.LayoutParams params;
private DataOutputStream dos;
[user=439709]@override[/user]
public IBinder onBind(Intent intent) {
MainActivity.log("onBind called o_o");
return null;
}
[user=439709]@override[/user]
public void onCreate() {
MainActivity.log("Service.onCreate");
super.onCreate();
try {
java.lang.Process p = Runtime.getRuntime().exec("su");
dos = new DataOutputStream(p.getOutputStream());
} catch (IOException ex) {
MainActivity.log(ex.getMessage());
dos = null;
}
windowManager = (WindowManager)
getSystemService(WINDOW_SERVICE);
mkv = new MissedKeysView(this, this);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
params.width = MissedKeysView.keySize;
params.height = MissedKeysView.keySize;
windowManager.addView(mkv, params);
MainActivity.log("Service started");
}
[user=439709]@override[/user]
public void onDestroy () {
super.onDestroy ();
if (mkv != null) windowManager.removeView(mkv);
MainActivity.log("Ssrvice is ended");
}
public void extend(boolean state) {
params.height = mkv.keySize * (state ? MissedKeysView.keys : 1);
windowManager.updateViewLayout(mkv, params);
}
public void sendKey(int code) {
if (dos == null) MainActivity.log("dos is null");
try {
dos.writeBytes("input keyevent " + code + "\n");
dos.flush();
MainActivity.log("" + code);
} catch (IOException e) {
MainActivity.log("wtf?");
}
}
}
MissedKeysView:
Code:
package com.tsk.mk;
import android.content.*;
import android.graphics.*;
import android.view.*;
import android.view.View.*;
import java.io.*;
public class MissedKeysView extends View
implements OnTouchListener {
final static int keySize = 64;
final static String[] labels = {":", "+", "-", "^", "v", "o", "<", ">"};
final private int[] codes = {-1, 24, 25, 19, 20, 23, 21, 22};
final static int keys = 3; //max shown keys
MissedKeysService mks;
Paint bgP; //background
Paint hbgP; //highlighted bg
Paint tP; //text
int selected = -1; //active key
public MissedKeysView(Context context, MissedKeysService mks) {
super(context);
this.mks = mks;
bgP = new Paint();
bgP.setARGB(64, 128, 128, 128);
hbgP = new Paint();
hbgP.setARGB(64, 255, 128, 0);
tP = new Paint();
tP.setARGB(128, 255, 255, 255);
tP.setTextSize(keySize);
tP.setTextAlign(Paint.Align.CENTER);
setOnTouchListener(this);
}
[user=439709]@override[/user]
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(int i=0; i<getHeight()/keySize; i++) {
canvas.drawCircle(keySize/2,
keySize/2 + i*keySize, keySize/2,
(i == selected ? hbgP : bgP));
canvas.drawText(labels[i], keySize/2, i*keySize + keySize*3/4, tP);
}
}
[user=439709]@override[/user]
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
selected = (int) (event.getY()/keySize);
if (selected == 0) mks.extend((int) getHeight() <= keySize);
else mks.sendKey(codes[selected]);
break;
case MotionEvent.ACTION_UP:
selected =-1;
}
invalidate();
return super.onTouchEvent(event);
}
}
AndroidManifest:
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tsk.mk"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="11" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".MainActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MissedKeysService"
android:exported="true" >
</service>
</application>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
</manifest>
@Torsionick do you have the permission INJECT_EVENTS
---------------------------------
Phone : Nexus 4
OS:
Pure KitKat 4.4.2 stock, no root, no mods
---------------------------------
4d 61 73 72 65 70 75 73 20 66 74 77
Gesendet von Tapatalk
Masrepus said:
@Torsionick do you have the permission INJECT_EVENTS
Click to expand...
Click to collapse
Thanks for participating in solving.
The reason was somewhere else - after executing "export LD_LIBRARY_PATH=/system/lib" all works fine. Thread is over.
I'm trying to make an app that displays and image which will be downloaded in background in an IntentService class. When the IntentService finishes to download it sends the intent to be catched by a BroadcastReceiver in the MainActivity but I'm getting this error:
Code:
07-17 14:27:21.003 19189-19189/com.example.matt95.myapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.matt95.myapplication, PID: 19189
java.lang.RuntimeException: Error receiving broadcast Intent { act=TRANSACTION_DONE flg=0x10 (has extras) } in [email protected]
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java)
at android.os.Handler.handleCallback(Handler.java)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.app.ActivityThread.main(ActivityThread.java)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.matt95.myapplication.MyActivity$1.onReceive(MyActivity.java:74)
************at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java)
************at android.os.Handler.handleCallback(Handler.java)
************at android.os.Handler.dispatchMessage(Handler.java)
************at android.os.Looper.loop(Looper.java)
************at android.app.ActivityThread.main(ActivityThread.java)
************at java.lang.reflect.Method.invokeNative(Native Method)
************at java.lang.reflect.Method.invoke(Method.java)
This is MainActivity class:
Code:
package com.example.matt95.myapplication;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
public class MyActivity extends Activity {
ProgressDialog pd;
// Custom BroadcastReceiver for catching and showing images
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
}
@Override
protected void onStart() {
super.onStart();
Intent i = new Intent(this, ImageIntentService.class);
i.putExtra("url", "http://samsung-wallpapers.com/uploads/allimg/130527/1-13052F02118.jpg");
startService(i);
pd = ProgressDialog.show(this, "Fetching image", "Go intent service go!");
}
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ImageIntentService.TRANSACTION_DONE);
registerReceiver(imageReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(imageReceiver);
}
private BroadcastReceiver imageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String location = intent.getExtras().getString("imageLocation");
if (location == null || location.length() == 0) {
String failedString = "Failed to download image";
Toast.makeText(context, failedString, Toast.LENGTH_LONG).show();
}
File imageFile = new File(location);
if (!imageFile.exists()) {
pd.dismiss();
String downloadFail = "Unable to download the image";
Toast.makeText(context, downloadFail, Toast.LENGTH_LONG).show();
return;
}
Bitmap image = BitmapFactory.decodeFile(location);
ImageView iv = (ImageView) findViewById(R.id.show_image);
iv.setImageBitmap(image);
pd.dismiss();
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
This is the IntentService class:
Code:
package com.example.matt95.myapplication;
import android.app.IntentService;
import android.content.Intent;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class ImageIntentService extends IntentService {
private File cacheDir;
private static final String CACHE_FOLDER = "/myapp/image_cache/";
public static String TRANSACTION_DONE = "com.example.matt95.myapplication.ImageIntentService.TRANSACTION_DONE";
//Constructor method
public ImageIntentService() {
super("ImageIntentService");
}
@Override
public void onCreate() {
super.onCreate();
String tmpLocation = Environment.getExternalStorageDirectory().getPath() + CACHE_FOLDER;
cacheDir = new File(tmpLocation);
if (!cacheDir.exists())
cacheDir.mkdirs();
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent.hasExtra("url")) {
String remoteUrl = intent.getExtras().getString("url");
String imageLocation;
String fileName = remoteUrl.substring(remoteUrl.lastIndexOf(File.separator) + 1);
File tmpImage = new File(cacheDir + "/" + fileName);
if (tmpImage.exists()) {
imageLocation = tmpImage.getAbsolutePath();
notifyFinished(imageLocation, remoteUrl);
stopSelf();
return;
}
try {
URL url = new URL(remoteUrl);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
if (httpCon.getResponseCode() != 200)
throw new Exception("Failed to connect");
InputStream is = httpCon.getInputStream();
FileOutputStream fos = new FileOutputStream(tmpImage);
writeStream(is, fos);
fos.flush();
fos.close();
is.close();
imageLocation = tmpImage.getAbsolutePath();
notifyFinished(imageLocation, remoteUrl);
} catch (Exception e) {
Log.e("Service", "Failed!", e);
}
}
}
private void writeStream(InputStream is, OutputStream fos) throws Exception {
byte buffer[] = new byte[80000];
int read = is.read(buffer);
while (read != -1) {
fos.write(buffer, 0, read);
read = is.read(buffer);
}
}
private void notifyFinished(String imageLocation, String remoteUrl) {
Intent i = new Intent(TRANSACTION_DONE);
i.putExtra("imageLocation", imageLocation);
i.putExtra("url", remoteUrl);
ImageIntentService.this.sendBroadcast(i);
}
}
And this is the Manifest file:
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.matt95.myapplication" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MyActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ImageIntentService" />
</application>
</manifest>
What am I doing wrong?
Code:
Caused by: java.lang.NullPointerException
at com.example.matt95.myapplication.MyActivity$1.onReceive(MyActivity.java:74)
tells you there, you are asking an object that is of type "x" that is NULL to do something on line 74
Why not just use the picasso library or similar to download the image asynchronously in the background?
Sent from my HTC One using Tapatalk
deanwray said:
Code:
Caused by: java.lang.NullPointerException
at com.example.matt95.myapplication.MyActivity$1.onReceive(MyActivity.java:74)
tells you there, you are asking an object that is of type "x" that is NULL to do something on line 74
Click to expand...
Click to collapse
Thanks, I knew that but I'lll take a closer look at the code again :good:
Jonny said:
Why not just use the picasso library or similar to download the image asynchronously in the background?
Sent from my HTC One using Tapatalk
Click to expand...
Click to collapse
I'm a beginner in Android application so I don't have the proper knowledge right now, thanks for the suggestion though, I'll definitely try to take a look at that library :good:
matt95 said:
Thanks, I knew that but I'lll take a closer look at the code again :good:
I'm a beginner in Android application so I don't have the proper knowledge right now, thanks for the suggestion though, I'll definitely try to take a look at that library :good:
Click to expand...
Click to collapse
Better use asynctask for loading images
Sent from my Moto G using XDA Premium 4 mobile app
arpitkh96 said:
Better use asynctask for loading images
Sent from my Moto G using XDA Premium 4 mobile app
Click to expand...
Click to collapse
Yeah but I also need to download it and then load it, and it's not good to download that amount of data on the main thread
matt95 said:
Yeah but I also need to download it and then load it, and it's not good to download that amount of data on the main thread
Click to expand...
Click to collapse
AsyncTask runs in the background on a separate thread via the doInBackground method.
Sent from my HTC One using Tapatalk
Also, when there is a possibility that one of the objects included in the intent is null you can trap the error with a try/catch around the sendBroadcast() to prevent the exception from crashing the entire app.