how to read pdf file file in android studio - android

I'm a beginner in android development , I want to make android app that can read pdf files. the pdf files that i have is with large contests (each pdf file around 60 mb) , as i searched i need to store the files in the server like website or something ( i don't know exactly is that what i need ) if i will store the files on server how can i make the users read the pdf files without downloading them into their phones? .
i found that i need to use web view but i'm not sure if this is the right way . and if what i'm thinking is wrong way please tell me what is the right way .i hope someone will help me because i'm searching for this and i'm not finding any specific answer .thank you

You can view a pdf file in an android project in different ways. I will describe some of them here-
1. Using Library:
Steps are below:
Installation
Add to build.gradle:
implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'
ProGuard
If you are using ProGuard, add following rule to proguard config file:
-keep class com.shockwave.**
Include PDFView in your layout
<com.github.barteksc.pdfviewer.PDFView
android:id="#+id/pdfView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Further link is here
2. Load pdf url into webview:
webview = (WebView)findViewById(R.id.webview);
progressbar = (ProgressBar) findViewById(R.id.progressbar);
webview.getSettings().setJavaScriptEnabled(true);
String filename = file_url_with_name;
webview.loadUrl(file_url + filename);
webview.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
// do your stuff here
progressbar.setVisibility(View.GONE);
}
});
3. Manually show PDF file into Imageview
// Example for creating manual PDF viewer into imageview used butterknife view binding<br/>
public class PdfRenderActivity extends AppCompatActivity {
#BindView(R.id.pdf_image) ImageView imageViewPdf;
#BindView(R.id.button_pre_doc) FloatingActionButton prePageButton;
#BindView(R.id.button_next_doc) FloatingActionButton nextPageButton;
private static final String FILENAME = "report.pdf";
private int pageIndex;
private PdfRenderer pdfRenderer;
private PdfRenderer.Page currentPage;
private ParcelFileDescriptor parcelFileDescriptor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pdf_render);
ButterKnife.bind(this);
pageIndex = 0;
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
protected void onStart() {
super.onStart();
try {
openRenderer(getApplicationContext());
showPage(pageIndex);
} catch (IOException e) {
e.printStackTrace();
}
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void onStop() {
try {
closeRenderer();
} catch (IOException e) {
e.printStackTrace();
}
super.onStop();
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#OnClick(R.id.button_pre_doc)
public void onPreviousDocClick(){
showPage(currentPage.getIndex() - 1);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#OnClick(R.id.button_next_doc)
public void onNextDocClick(){
showPage(currentPage.getIndex() + 1);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void openRenderer(Context context) throws IOException {
// In this sample, we read a PDF from the assets directory.
File file = new File(context.getCacheDir(), FILENAME);
if (!file.exists()) {
// Since PdfRenderer cannot handle the compressed asset file directly, we copy it into
// the cache directory.
InputStream asset = context.getAssets().open(FILENAME);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
// This is the PdfRenderer we use to render the PDF.
if (parcelFileDescriptor != null) {
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
}
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void closeRenderer() throws IOException {
if (null != currentPage) {
currentPage.close();
}
pdfRenderer.close();
parcelFileDescriptor.close();
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void showPage(int index) {
if (pdfRenderer.getPageCount() <= index) {
return;
}
// Make sure to close the current page before opening another one.
if (null != currentPage) {
currentPage.close();
}
// Use `openPage` to open a specific page in PDF.
currentPage = pdfRenderer.openPage(index);
// Important: the destination bitmap must be ARGB (not RGB).
Bitmap bitmap = Bitmap.createBitmap(currentPage.getWidth(), currentPage.getHeight(),
Bitmap.Config.ARGB_8888);
// Here, we render the page onto the Bitmap.
// To render a portion of the page, use the second and third parameter. Pass nulls to get
// the default result.
// Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
currentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// We are ready to show the Bitmap to user.
imageViewPdf.setImageBitmap(bitmap);
updateUi();
}
/**
* Updates the state of 2 control buttons in response to the current page index.
*/
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void updateUi() {
int index = currentPage.getIndex();
int pageCount = pdfRenderer.getPageCount();
prePageButton.setEnabled(0 != index);
nextPageButton.setEnabled(index + 1 < pageCount);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public int getPageCount() {
return pdfRenderer.getPageCount();
}
}
Doc is here

Related

Compare a file in the device with one in firebase

My app download html files from the database the first time the app is opened.
When a button is clicked I want to check every html file and download an "updated" html version (Only if the html in the device is different from the one in the database)
How can I do that kind of comparison?
My main activity onCreate with a boolean to check if is the first time the app is opened then a function getFiles() is called to download every html file.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_horarios = (Button)findViewById(R.id.btn_horarios);
Boolean isrunfirst = getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("first", true);
if(isrunfirst){
getFiles();
getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit().putBoolean("first", false).apply();
} else {
}
}
getFiles function with a loop used to "loop" through a String array containing the name of the files, with the name the file is retrieved from the database and finally the file is saved using a function saveFile()
public void getFiles(){
FirebaseStorage storage = FirebaseStorage.getInstance();
final StorageReference storageRef = storage.getReference();
final String[] grupos = getResources().getStringArray(R.array.array_grupos);
for(int i = 0; i < 97; i += 1) {
final int finalI = i;
StorageReference htmlRef = storageRef.child("grupos/" + grupos[finalI] + ".html");
final long ONE_MEGABYTE = 1024 * 1024;
htmlRef.getBytes(ONE_MEGABYTE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
#Override
public void onSuccess(byte[] bytes) {
saveFile(grupos[finalI] + ".html", bytes);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
}
});
}
}
saveFile() takes the file name and the bytes, the bytes are converted into a string an saved.
private void saveFile(String file, byte[] bytes) {
try {
String text = new String(bytes, "UTF-8");
FileOutputStream fis = openFileOutput(file, Context.MODE_PRIVATE);
fis.write(text.getBytes());
fis.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
}

Decoding image in AsyncTask

I'm new to android development and I'm a bit confused regarding decoding and scaling bitmaps using AsyncTask. I've read the android development site and it didn't help my understanding. My question is how exactly is this done? My goal is to decode and scale multiple images and placed them in ImageViews.
Do I code the decoding and scaling within a doInBackground method? Any help will be great appreciated!
Yes, you should do anything you can on the doInBackground. Only when your image is ready than use "return" to call onPostExecute and in onPostExecute you should set the bitmap to the imageView.
This code sample is from my recipe app, and should illustrate what you are asking. The images are read in as base64 encoded data from a web service, so need to be decoded before they can be shown within a ListView.
The code first of all checks for cached images, if not it decodes them in the background using AsyncTask, and writes the result to cache for future use.
The decoding is done in doInBackground, and the display/write to cache is done in onPostExecute.
Hole this helps.
mRecipeAdapter = new ArrayAdapter<Recipe>(getActivity(), R.layout.listrow, mData2){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
if (null == convertView) {
row = mInflater.inflate(R.layout.recipe_listrow, null);
} else {
row = convertView;
}
TextView tv = (TextView) row.findViewById(R.id.recipe_title);
ImageView iv = (ImageView) row.findViewById(R.id.recipe_image);
iv.setImageBitmap(null);
Recipe r = getItem(position);
tv.setText(r.title);
File cacheFile = new File(mCacheDir, ""+r.identity.hashCode());
if (cacheFile.exists()){
FileInputStream fis;
try {
fis = new FileInputStream(cacheFile);
Bitmap bmp = BitmapFactory.decodeStream(fis);
iv.setImageBitmap(bmp);
bmp = null;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
// Get image asynchronously from database
new AsyncImages(iv).execute(r);
}
return row;
}
class AsyncImages extends AsyncTask<Recipe, Void, Recipe> {
private static final long MAX_SIZE = 5242880L; // 5MB
private final WeakReference<ImageView> imageViewReference;
public AsyncImages(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
#Override
protected Recipe doInBackground(Recipe... r) {
Recipe recipe = r[0];
double heapRemaining = Runtime.getRuntime().freeMemory(); //amount available in heap
Log.i("MEM REM", Double.toString(heapRemaining));
String imageString = SchwartzRecipesBaseActivity.getThumbnailImageFor(recipe.identity);
recipe.thumb = StringToBitMap(imageString);
imageString = null;
return recipe;
}
protected void onPostExecute(Recipe r) {
if (isCancelled()) {
r.thumb = null;
return;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(r.thumb);
// Write to cache file
// Make space if needed
long sz = getDirSize();
if (sz>MAX_SIZE){
makeSomeSpace(r.thumb.getByteCount());
}
File cacheFile = new File(mCacheDir, ""+r.identity.hashCode());
try {
// Create a file at the file path, and open it for writing obtaining the output stream
cacheFile.createNewFile();
FileOutputStream fos = new FileOutputStream(cacheFile);
// Write the bitmap to the output stream (and thus the file) in PNG format (lossless compression)
r.thumb.compress(CompressFormat.JPEG, 100, fos);
// Flush and close the output stream
fos.flush();
fos.close();
} catch (Exception e) {
// Log anything that might go wrong with IO to file
Log.e("CACHE", "Error when saving image to cache. ", e);
}
}
}
}
private void makeSomeSpace(long bytes) {
long bytesDeleted = 0;
File[] files = mCacheDir.listFiles();
Arrays.sort(files, new Comparator<File>(){
public int compare(File f1, File f2)
{
return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
} });
for (File file : files) {
bytesDeleted += file.length();
file.delete();
if (bytesDeleted >= bytes) {
break;
}
}
}
private long getDirSize() {
if (mCacheDir == null) return 0;
long size = 0;
File[] files = mCacheDir.listFiles();
for (File file : files) {
if (file.isFile()) {
size += file.length();
}
}
return size;
}
}
private Bitmap StringToBitMap(String encodedString) {
try{
byte [] encodeByte=Base64.decode(encodedString,Base64.DEFAULT);
Bitmap bitmap=BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
return bitmap;
}catch(Exception e){
e.getMessage();
return null;
}
}
};
setListAdapter(mRecipeAdapter);
Do all the heavy loading stuff in the doInBackground method, and just set the image afterwards in the onPostExecute method.
Enable the strict mode (http://developer.android.com/reference/android/os/StrictMode.html) to make sure you have done everything right (will write a warning into your logcat in case you are doing something on the UI thread you shouldn't be doing):
public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
super.onCreate();
}
But I highly recommend to use a library like volley or Picasso whenever you are working with images from external sources. Take a look at the following question: Local image caching solution for Android: Square Picasso vs Universal Image Loader

Create downloadable custom theme and apply it during run time

I'm making an Android app that needs to allow client to maintain the resources from their server which would include strings, drawables etc.
I've already created a mechanism for downloading a zip file with all these files, and they're able to change strings pretty easy, I've also created a mechanism that allows the client to change bg color for UI controls, to change width, height etc but I have a feeling that there must be a better way to create all this.
So I believe the real question is:
What's the best practice to create a custom theme, deploy it on server, make the app download it, and apply it to app afterwards?
I know how to create custom theme and how to deploy it with the app, and how to apply it during runtime, but the problem here is that resources are pre-compiled and once you create APK there's no way for developer to change them which would be required in order to add new themes/drawables/styles/strings.
Do I need to create a custom mechanism for all this (loading images, styles, strings etc from the file system) and to apply them during runtime by creating my own controls that would do that in constructor for example or is there a way to do this properly :)? ( how does Swiftkey do this with all the keyboard themes, and how do similar apps do it allowing the users to download theme and apply it after that )?
I'm sorry if I didn't see similar question, I really tried to find an answer myself during past 2 days, but I failed to find anything useful, so this is my last chance to get a constructive answer :).
The closest to solution i need was this answer: Changing app theme at runtime using using external theme file but I've already made that functionality, and i know i can change colors like that, but the problem is that i would like to be able to change things like borders, on button pressed state etc that require resources other than simple color value :(.
Thanks heaps!
P.S. I've also read about the extension files so is that something i need to consider while thinking about this, or do i need to look elsewhere? The problem with obb files is that they must be deployed over PlayStore and that's not "perfect" for the client because they need to pack it by using jobb, and to deploy it to PlayStore which is too technical for them, so they would prefer creating a zip file, putting it on server, and the app should do the rest :).
I've finally decided to solve this by making a custom system for handling drawables, strings etc so now i have a custom class called "ResourceManager" that handles what needs to be loadad and how, and themes are distributed as a zip file which app downloads, extracts and later uses.
I had to compile nine patch images by myself before putting them in zip file, and I did that using "abrc" from here: http://forum.xda-developers.com/showthread.php?t=785012
I've also created a simple bash script that goes recursively through custom folder and compiles all nine patch images with abrc.
I've also created a simple helper in the ResourceManager that checks and tells me the screen density so i can normally support images in hdpi, xhdpi etc densities, and finally i don't re-create the images every time i need them, i save them in a static list of HashMap so i can reuse the ones I've already created and that way i hope to prevent wasting too much phone's memory :).
OK that's all in short lines, if anyone has any questions please let me know, i'll be glad to share this experience with anyone.
Cheers!
============ EDIT ============
Here's the class I ended up writing for this purpose (it downloads the file, checks for it's version, loads strings from JSON file rather than strings.xml etc)
NOTE: This is not a full class so some parts are missing, but I think it's more than enough to get the idea how I solved all this :)
/**
* Created by bojank on 7/28/2014.
* Class that handles custom resources downloaded from server
*/
public class ResourceManager {
// List of ninePatchImages in the application
private static ArrayList<HashMap<String, NinePatchDrawable>> ninePatchHashMaps;
private static ArrayList<HashMap<String, Drawable>> imagesHashMaps;
private static ImageLoader imageLoader;
// Context for methods
public static Context ctx;
// JSONObject with all strings
private static JSONObject joString;
// JSONObject with all styles
private static JSONObject joStyles;
// String with current active lang code
private static String currentLanguage;
private static String sdcardPath;
// Private consturctor to prevent creating a class instance
private ResourceManager() {
}
/**
* Method that returns a translated string for given key
*
* #param key String
* #return String
*/
public static String getString(String module, String key) {
String output = ""; //String.format("[%s - %s]", module, key);
try {
if (getStringsFile() != null && getStringsFile().getJSONObject(module).has(key))
output = getStringsFile().getJSONObject(module).getString(key);
} catch (Exception e) {
// Force some default language if proper json file is missing for newly added language
currentLanguage = "en-US";
Helper.saveLocale(currentLanguage, ctx);
Helper.logError("ErrorFetchingString", e);
}
return output;
}
/**
* Method that returns JSONObject with string resources
* #return JSONObject
* #throws JSONException
*/
public static JSONObject getStringsFile() throws JSONException {
if (joString == null) {
String stringFileName = getResourcesPath() + "languages/" + getCurrentLanguage() + "/values.json";
String languageFile = Helper.readJsonFile(stringFileName);
if (languageFile != null) {
joString = new JSONObject(Helper.readJsonFile(stringFileName));
} else {
return null;
}
}
return joString.getJSONObject("strings");
}
/**
* Method that returns current language ("sr", "en"...)
* #return String
*/
public static String getCurrentLanguage() {
if (currentLanguage == null)
currentLanguage = Helper.getCurrentLanguage(ctx);
return currentLanguage;
}
/**
* Method that resets joString object and currentLanguage on language change
*/
public static void resetLanguage() {
joString = null;
currentLanguage = null;
}
/**
* Method that resets joStyles object on theme change
*/
public static void resetStyle() {
joStyles = null;
}
/**
* Method that deletes a directory from filesystem
* #param path File
* #return boolean
*/
public static boolean deleteDirectory(File path) {
if( path.exists() ) {
File[] files = path.listFiles();
for(int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
}
else {
files[i].delete();
}
}
}
return(path.delete());
}
/**
* Method that get's the version of assets file
* #param url String
*/
public static String getAssetsVersion(String url) throws IOException {
Helper.logInfo("REQUEST URL:", url);
OkHttpClient client = new OkHttpClient();
// set connection timeut to 5min
client.setConnectTimeout(1, TimeUnit.MINUTES);
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
/**
* Method that downloads assets file from server
* #param url String
* #return String
* #throws IOException
*/
public static String getAssetsFile(String url) throws IOException {
Helper.logInfo("REQUEST URL:", url);
OkHttpClient client = new OkHttpClient();
// set connection timeut to 5min
client.setConnectTimeout(1, TimeUnit.MINUTES);
Request request = new Request.Builder()
.url(url)
.header("User-Agent", MyApplication.USER_AGENT)
.build();
Response response = client.newCall(request).execute();
InputStream inputStreamFile = response.body().byteStream();
try {
// Output stream
String outputFileName = Environment.getExternalStorageDirectory().toString() + "/assets.zip";
File deleteFile = new File(outputFileName);
deleteFile.delete();
OutputStream output = new FileOutputStream(outputFileName);
byte data[] = new byte[1024];
int count;
// writing data to file
while ((count = inputStreamFile.read(data)) != -1)
output.write(data, 0, count);
// flushing output
output.flush();
// closing streams
output.close();
inputStreamFile.close();
return outputFileName;
} catch (Exception e) {
Helper.logError("Download Resursa", e);
return "ERROR";
}
}
public static void setStyle(View v, String styleName) {
try {
if (styleName == null || styleName.equals("")) {
if (v instanceof EditText)
processStyle(v, getStylesFile().getJSONObject("EditText"));
} else
processStyle(v, getStylesFile().getJSONObject(styleName));
} catch (Exception e) {
Helper.logError("Setting Styles", e);
}
}
private static void setBackground(View v, Drawable d) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
v.setBackgroundDrawable(d);
} else {
v.setBackground(d);
}
}
public static JSONObject getStylesFile() throws JSONException {
if (joStyles == null) {
String stylesFileName = getResourcesPath() + "styles/properties.json";
joStyles = new JSONObject(Helper.readJsonFile(stylesFileName));
}
return joStyles;
}
public static void processStyle(View v, JSONObject joStyle) {
if(joStyle != null) {
try {
// used for layout margins
LinearLayout.LayoutParams layoutParams = null;
if (Helper.isValidParameter(joStyle, "backgroundColor"))
v.setBackgroundColor(Color.parseColor(joStyle.getString("backgroundColor")));
if (Helper.isValidParameter(joStyle, "backgroundImage"))
setBackground(v, loadNinePatchFromFilesystem(getImagesPath() + joStyle.getString("backgroundImage")));
if (v instanceof TextView) {
applyTextViewParameters(v, joStyle);
} else if (v instanceof ListView) {
if (Helper.isValidParameter(joStyle, "dividerColor")) {
((ListView) v).setDivider(new ColorDrawable(Color.parseColor(joStyle.getString("dividerColor"))));
((ListView) v).setDividerHeight(Helper.convertDpToPixel(1));
}
if (Helper.isValidParameter(joStyle, "dividerHeight")) {
((ListView) v).setDividerHeight(Helper.convertDpToPixel(joStyle.getInt("dividerHeight")));
}
} else if (v instanceof UnderlinePageIndicator) {
if (Helper.isValidParameter(joStyle, "backgroundColor")) {
v.setBackgroundColor(Color.parseColor(joStyle.getString("backgroundColor")));
}
if (Helper.isValidParameter(joStyle, "selectedColor")) {
((UnderlinePageIndicator) v).setSelectedColor(Color.parseColor(joStyle.getString("selectedColor")));
}
} else if (v instanceof StyleableBackground) {
if (Helper.isValidParameter(joStyle, "backgroundColor")) {
View background = v.findViewById(R.id.llBackground);
if (background != null) {
background.setBackgroundColor(Color.parseColor(joStyle.getString("backgroundColor")));
}
}
if (Helper.isValidParameter(joStyle, "borderTopColor")) {
View topBorder = v.findViewById(R.id.llTopBorder);
if (topBorder != null) {
topBorder.setBackgroundColor(Color.parseColor(joStyle.getString("borderTopColor")));
if (Helper.isValidParameter(joStyle, "borderTopHeight")) {
topBorder.setMinimumHeight(Helper.convertDpToPixel(joStyle.getInt("borderTopHeight")));
}
}
}
if (Helper.isValidParameter(joStyle, "borderBottomColor")) {
View bottomBorder = v.findViewById(R.id.llBottomBorder);
if (bottomBorder != null) {
bottomBorder.setBackgroundColor(Color.parseColor(joStyle.getString("borderBottomColor")));
if (Helper.isValidParameter(joStyle, "borderBottomHeight")) {
bottomBorder.setMinimumHeight(Helper.convertDpToPixel(joStyle.getInt("borderBottomHeight")));
}
}
}
if (Helper.isValidParameter(joStyle, "backgroundImage")) {
ImageView ivBackgroundImage = (ImageView) v.findViewById(R.id.ivBackgroundImage);
if (ivBackgroundImage != null) {
BitmapDrawable d = (BitmapDrawable) ResourceManager.loadImageFromFilesystem(ResourceManager.getImagesPath() + joStyle.getString("backgroundImage"));
d.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
d.setGravity(Gravity.FILL_HORIZONTAL | Gravity.FILL_VERTICAL);
setBackground(ivBackgroundImage, d);
}
}
}
if(Helper.isValidParameter(joStyle, "width"))
v.setMinimumWidth(joStyle.getInt("width"));
if(Helper.isValidParameter(joStyle, "height"))
v.setMinimumHeight(joStyle.getInt("height"));
if(Helper.isValidParameter(joStyle, "padding"))
v.setPadding(joStyle.getInt("padding"), joStyle.getInt("padding"), joStyle.getInt("padding"), joStyle.getInt("padding"));
if(Helper.isValidParameter(joStyle, "paddingLeft"))
v.setPadding(joStyle.getInt("paddingLeft"), v.getPaddingTop(), v.getPaddingRight(), v.getPaddingBottom());
if(Helper.isValidParameter(joStyle, "paddingTop"))
v.setPadding(v.getPaddingLeft(), joStyle.getInt("paddingTop"), v.getPaddingRight(), v.getPaddingBottom());
if(Helper.isValidParameter(joStyle, "paddingRight"))
v.setPadding(v.getPaddingLeft(), v.getPaddingTop(), joStyle.getInt("paddingRight"), v.getPaddingBottom());
if(Helper.isValidParameter(joStyle, "paddingBottom"))
v.setPadding(v.getPaddingLeft(), v.getPaddingTop(), v.getPaddingRight(), joStyle.getInt("paddingBottom"));
if(Helper.isValidParameter(joStyle, "margin")) {
layoutParams = new LinearLayout.LayoutParams(v.getLayoutParams());
layoutParams.setMargins(joStyle.getInt("margin"), joStyle.getInt("margin"), joStyle.getInt("margin"), joStyle.getInt("margin"));
}
if(Helper.isValidParameter(joStyle, "marginLeft")) {
layoutParams = new LinearLayout.LayoutParams(v.getLayoutParams());
layoutParams.setMargins(joStyle.getInt("marginLeft"), layoutParams.topMargin, layoutParams.rightMargin, layoutParams.bottomMargin);
}
if(Helper.isValidParameter(joStyle, "marginTop")) {
layoutParams = new LinearLayout.LayoutParams(v.getLayoutParams());
layoutParams.setMargins(layoutParams.leftMargin, joStyle.getInt("marginTop"), layoutParams.rightMargin, layoutParams.bottomMargin);
}
if(Helper.isValidParameter(joStyle, "marginRight")) {
layoutParams = new LinearLayout.LayoutParams(v.getLayoutParams());
layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin, joStyle.getInt("marginRight"), layoutParams.bottomMargin);
}
if(layoutParams != null)
v.setLayoutParams(layoutParams);
RelativeLayout.LayoutParams relativeLayoutParams = null;
if (Helper.isValidParameter(joStyle, "alignParentTop") && joStyle.getBoolean("alignParentTop")) {
relativeLayoutParams = new RelativeLayout.LayoutParams(v.getLayoutParams());
relativeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
}
if (Helper.isValidParameter(joStyle, "alignParentLeft") && joStyle.getBoolean("alignParentLeft")) {
relativeLayoutParams = new RelativeLayout.LayoutParams(v.getLayoutParams());
relativeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
}
if (Helper.isValidParameter(joStyle, "alignParentBottom") && joStyle.getBoolean("alignParentBottom")) {
relativeLayoutParams = new RelativeLayout.LayoutParams(v.getLayoutParams());
relativeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
}
if (Helper.isValidParameter(joStyle, "alignParentRight") && joStyle.getBoolean("alignParentRight")) {
relativeLayoutParams = new RelativeLayout.LayoutParams(v.getLayoutParams());
relativeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
}
if(Helper.isValidParameter(joStyle, "marginLeft")) {
relativeLayoutParams = new RelativeLayout.LayoutParams(v.getLayoutParams());
relativeLayoutParams.setMargins(joStyle.getInt("marginLeft"), relativeLayoutParams.topMargin, relativeLayoutParams.rightMargin, relativeLayoutParams.bottomMargin);
}
if(Helper.isValidParameter(joStyle, "marginTop")) {
relativeLayoutParams = new RelativeLayout.LayoutParams(v.getLayoutParams());
relativeLayoutParams.setMargins(relativeLayoutParams.leftMargin, joStyle.getInt("marginTop"), relativeLayoutParams.rightMargin, relativeLayoutParams.bottomMargin);
}
if(Helper.isValidParameter(joStyle, "marginRight")) {
relativeLayoutParams = new RelativeLayout.LayoutParams(v.getLayoutParams());
relativeLayoutParams.setMargins(relativeLayoutParams.leftMargin, relativeLayoutParams.topMargin, joStyle.getInt("marginRight"), relativeLayoutParams.bottomMargin);
}
if (relativeLayoutParams != null) {
v.setLayoutParams(relativeLayoutParams);
}
} catch (Exception e) {
Helper.logError("", e);
}
}
}
public static String getSdcardPath() {
if(sdcardPath == null)
sdcardPath = ctx.getApplicationInfo().dataDir;
return sdcardPath;
}
public static String getResourcesPath() {
return getSdcardPath() + "/resources/";
}
public static String getCSSPath() {
return getResourcesPath() + "default.css";
}
public static String getImagesPath() {
return getResourcesPath() + "images/" + ResourceConstants.getScreenDPI(ctx) + "/";
}
public static String getImagesPathNoDpi() {
return getResourcesPath() + "images/";
}
public static NinePatchDrawable loadNinePatchFromFilesystem(String filename) {
if(ninePatchHashMaps == null)
ninePatchHashMaps = new ArrayList<HashMap<String, NinePatchDrawable>>();
// check if we already have this filename so we can reuse it
for (int i = 0; i < ninePatchHashMaps.size(); i++) {
HashMap<String, NinePatchDrawable> row = ninePatchHashMaps.get(i);
if(row.containsKey(filename))
return row.get(filename);
}
NinePatchDrawable patchy = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(filename, options);
byte[] chunk = bitmap.getNinePatchChunk();
boolean result = NinePatch.isNinePatchChunk(chunk);
if (result)
patchy = new NinePatchDrawable(bitmap, chunk, new Rect(), null);
} catch (Exception e){
Helper.logError("NinePatchLoading",e);
}
if(patchy != null) {
HashMap<String, NinePatchDrawable> drawableImage = new HashMap<String, NinePatchDrawable>();
drawableImage.put(filename, patchy);
ninePatchHashMaps.add(drawableImage);
}
return patchy;
}
public static Drawable loadImageFromFilesystem(String filename) {
if(imagesHashMaps == null)
imagesHashMaps = new ArrayList<HashMap<String, Drawable>>();
// check if we already have this filename so we can reuse it
for (int i = 0; i < imagesHashMaps.size(); i++) {
HashMap<String, Drawable> row = imagesHashMaps.get(i);
if(row.containsKey(filename))
return row.get(filename);
}
Drawable image = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(filename, options);
if(bitmap == null)
bitmap = BitmapFactory.decodeFile(filename.replace(ResourceConstants.getScreenDPI(ctx) + "/", ""), options);
image = new BitmapDrawable(bitmap);
} catch (Exception e){
Helper.logError("ImageLoadingError",e);
}
if(image != null) {
HashMap<String, Drawable> drawableImage = new HashMap<String, Drawable>();
drawableImage.put(filename, image);
imagesHashMaps.add(drawableImage);
}
return image;
}
}

how can i save all images that exist online to my sd card once it has opened?

what i have is a grid view and i open the images online . but what i need to do is when the user open the app .. all of those images to be downloaded in the mobile phone automatically so when the user open the app again it will show up from the memory not online ..
please any help?? and what i have is 250 images maybe
and is there any other so i can call my images dynamically instead of calling them one by one??
here is an example of how i call my images:
private String urls[] = {
"http://transition-se.com/training_may/foodribbons.JPG",
"http://transition-se.com/training_may/clothribbon.JPG",
"http://transition-se.com/training_may/shoesribbon.JPG",
"http://transition-se.com/training_may/bagsribbon.JPG",
"http://transition-se.com/training_may/viewsribbon.JPG",
"http://transition-se.com/training_may/makeupribbon.JPG",
"http://transition-se.com/training_may/roomribbon.JPG",
"http://transition-se.com/training_may/watchesribbon.JPG"
};
You can do it like a hard way, or you can do it easy way.
You can make symple Asynk task and load images to files on your device.
Example:
private class Downloader extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
// show dialog loading here
}
#Override
protected Integer doInBackground(String... params) {
// for loop here
for(int i=0; i<params.lenght; i++) {
try {
URL url = new URL(params[i]);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream( file name here );
// add this file to global list, so you can used it after
byte[] b = new byte[1024];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
return 1;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
}
#Override
protected void onProgressUpdate(Void... values) {
// update loading dialog precents
}
#Override
protected void onPostExecute(Integer result) {
// hide loading dialog
if (result == 1) {
// all images loaded to files
}
}
}
Or you can use out of the box libs for this operation which i prefer, try this Picasso Asynk image loader, it will handle complex operation for you
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use.
Automatic memory and disk caching.

How to use assets as a source for osmdroid offline maps

I'm trying to use osmdroid for offline map usage in my app, but the thing which I'm not able to find is how to set the tile source from the /assets folder.
So I've got the tiles (from Mobile Atlas Creator), placed in /assets/maps.zip
and I'm trying something like this:
final ITileSource tileSource =
new XYTileSource("maps", null, 15, 17, 256, "png", "/assets");
mapview.setBuiltInZoomControls(true);
mapview.setTileSource(tileSource);
mapview.getController().setZoom(15);
mapview.setUseDataConnection(false);
.. which seems to be wrong some way. So can anybody point me on how to do that?
OK, the question has been asked a couple of years ago,
but there is still no clear info on how to use offline maps from the assets folder.
So here is my solution.
Create the maps with Mobile Atlas Creator.
I used Atlas format = osmdroid zip and maps source = OpenStreetMap 4UMaps.eu
Unzip the maps and put into your assets folder:
assets/map/14, where 14 - is for instance a folder with the corresponding zoom level (you will probably have several folders)
Add classes which I found somewhere on the internet:
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import org.osmdroid.ResourceProxy.string;
import org.osmdroid.tileprovider.tilesource.BitmapTileSourceBase;
import org.osmdroid.tileprovider.util.StreamUtils;
import java.io.InputStream;
/**
* Custom tile source,
* used to load map tiles from the assets
*/
public class AssetsTileSource extends BitmapTileSourceBase {
private final AssetManager mAssetManager;
public AssetsTileSource(final AssetManager assetManager, final String aName, final string aResourceId,
final int aZoomMinLevel, final int aZoomMaxLevel, final int aTileSizePixels,
final String aImageFilenameEnding) {
super(aName, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding);
mAssetManager = assetManager;
}
#Override
public Drawable getDrawable(final String aFilePath) {
InputStream inputStream = null;
try {
inputStream = mAssetManager.open(aFilePath);
if (inputStream != null) {
final Drawable drawable = getDrawable(inputStream);
return drawable;
}
} catch (final Throwable e) {
// Tile does not exist in assets folder.
// Ignore silently
} finally {
if (inputStream != null) {
StreamUtils.closeStream(inputStream);
}
}
return null;
}
}
and
/**
* Map tile provider, loads tile from assets folder
*/
public class MapTileFileAssetsProvider extends MapTileModuleProviderBase {
protected ITileSource mTileSource;
public MapTileFileAssetsProvider(final ITileSource pTileSource) {
super(OpenStreetMapTileProviderConstants.NUMBER_OF_TILE_FILESYSTEM_THREADS, OpenStreetMapTileProviderConstants.TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE);
mTileSource = pTileSource;
}
#Override
public boolean getUsesDataConnection() {
return false;
}
#Override
protected String getName() {
return "Assets Folder Provider";
}
#Override
protected String getThreadGroupName() {
return "assetsfolder";
}
#Override
protected Runnable getTileLoader() {
return new TileLoader();
}
#Override
public int getMinimumZoomLevel() {
return mTileSource != null ? mTileSource.getMinimumZoomLevel() : Constants.MAP_ZOOM_ZOOM_MAX;
}
#Override
public int getMaximumZoomLevel() {
return mTileSource != null ? mTileSource.getMaximumZoomLevel() : Constants.MAP_ZOOM_ZOOM_MIN;
}
#Override
public void setTileSource(final ITileSource pTileSource) {
mTileSource = pTileSource;
}
private class TileLoader extends MapTileModuleProviderBase.TileLoader {
#Override
public Drawable loadTile(final MapTileRequestState pState) throws CantContinueException {
if (mTileSource == null) {
return null;
}
final MapTile pTile = pState.getMapTile();
String path = mTileSource.getTileRelativeFilenameString(pTile);
Drawable drawable;
try {
drawable = mTileSource.getDrawable(path);
} catch (final LowMemoryException e) {
// low memory so empty the queue
throw new CantContinueException(e);
}
return drawable;
}
}
}
Add the constants:
// map min zoom level
public static final int MAP_ZOOM_ZOOM_MIN = 12;
// map max zoom level
public static final int MAP_ZOOM_ZOOM_MAX = 14;
// maps folder name in assets
public static final String MAP_ASSETS_FOLDER_NAME = "map";
As you probably guessed, they represent minimum and maximum zoom level, which we previously created with the Mobile Atlas Creator.
The last, but not the least,
the snippet of implementation code:
// making the map not use internet
mBinding.mapView.setUseDataConnection(false);
// Initializing the tile provider to use offline maps from the assets
// This will load for instance from /map/14/12345/12345.png
AssetsTileSource tileSource = new AssetsTileSource(
getAssets(),
Constants.MAP_ASSETS_FOLDER_NAME,
ResourceProxy.string.offline_mode,
Constants.MAP_ZOOM_ZOOM_MIN,
Constants.MAP_ZOOM_ZOOM_MAX,
256, ".png");
MapTileModuleProviderBase moduleProvider = new
MapTileFileAssetsProvider(tileSource);
SimpleRegisterReceiver simpleReceiver = new
SimpleRegisterReceiver(this);
MapTileProviderArray tileProviderArray = new
MapTileProviderArray(tileSource, simpleReceiver, new
MapTileModuleProviderBase[] { moduleProvider });
mBinding.mapView.setTileProvider(tileProviderArray);
// not forget to invalidate the map on zoom
mBinding.mapView.setMapListener(new MapListener() {
#Override
public boolean onScroll(ScrollEvent scrollEvent) {
return false;
}
#Override
public boolean onZoom(ZoomEvent zoomEvent) {
mBinding.mapView.invalidate();
return false;
}
});
asset path is "file:///android_asset/" if you need a inputstream you get it via AssetManager.
Take a look at BitmapAssetTileSource. Also the iBurn-2012 might be useful to see it in action.

Categories

Resources