Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am new to Android. I am developing an application that requires a user signature. How can I capture a signature in Android?
Your question is a little too broad. Try asking a question about a specific problem, not "how do I do something general". See the FAQ for more information about how to ask a question.
Here is a vague idea though:
You'll want to have a canvas object that can allow the user to draw to the screen. Here is a link on SO about it. Android drawing a line to follow your finger
Then you'll want to output that bitmap as a file: Save bitmap to location
You can do this in two ways:
1. Your own Implementation
You can use canvas to draw signatures. Use paint object to set signature stroke size & color.
2. Simply use library
See SignatureView library. It will do all, what you want.
https://github.com/zahid-ali-shah/SignatureView
Here's how I have capture human signature and save image using this example:
https://demonuts.com/android-capture-digital-signature/
First add following to your gradle:
repositories {
jcenter()
}
repositories {
maven {
url 'https://dl.bintray.com/zahid/maven/'
}
}
dependencies {
compile 'com.kyanogen.signatureview:signature-view:1.0'
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.parsaniahardik.signaturedemo.MainActivity">
<com.kyanogen.signatureview.SignatureView
xmlns:sign="http://schemas.android.com/apk/res-auto"
android:id="#+id/signature_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
sign:penSize="5dp"
sign:backgroundColor="#ffffff"
sign:penColor="#000000"
sign:enableSignature="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/clear"
android:text="clear"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/save"
android:text="save"/>
</LinearLayout>
MainActivity.java:
package com.example.parsaniahardik.signaturedemo;
import android.graphics.Bitmap;
import android.media.MediaScannerConnection;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.kyanogen.signatureview.SignatureView;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity {
Bitmap bitmap;
Button clear,save;
SignatureView signatureView;
String path;
private static final String IMAGE_DIRECTORY = "/signdemo";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
signatureView = (SignatureView) findViewById(R.id.signature_view);
clear = (Button) findViewById(R.id.clear);
save = (Button) findViewById(R.id.save);
clear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
signatureView.clearCanvas();
}
});
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bitmap = signatureView.getSignatureBitmap();
path = saveImage(bitmap);
}
});
}
public String saveImage(Bitmap myBitmap) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File wallpaperDirectory = new File(
Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY /*iDyme folder*/);
// have the object build the directory structure, if needed.
if (!wallpaperDirectory.exists()) {
wallpaperDirectory.mkdirs();
Log.d("hhhhh",wallpaperDirectory.toString());
}
try {
File f = new File(wallpaperDirectory, Calendar.getInstance()
.getTimeInMillis() + ".jpg");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
MediaScannerConnection.scanFile(MainActivity.this,
new String[]{f.getPath()},
new String[]{"image/jpeg"}, null);
fo.close();
Log.d("TAG", "File Saved::--->" + f.getAbsolutePath());
return f.getAbsolutePath();
} catch (IOException e1) {
e1.printStackTrace();
}
return "";
}
}
Don't forget to give READ-WRITE permission in manifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Many applications ask their users to accept an agreement, but I can't think of one I've used that's asked me for my actual signature.
Is there a good reason that your users aren't able to accept yr agreement in the usual way? (via a check box or by hitting a button marked 'I accept'?)
Why is a graphical representation of the users signature required?
It's difficult to write using a finger, and it's even more difficult to
write (using a finger) on a smart phone screen.
There are also privacy concerns relating to obtaining a graphical representation of a user's signature. Once obtained, I have no idea what your company will do with my signature. A signature is a valuable piece of personal information, which could ultimately be used for identity theft.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
I know this question has been asked many times but it's still unclear for me if there is an existing and properly working library to natively display PDF documents.
I only want to view a PDF document which is stored inside my app. Opening a new Activity is ok for me, I don't need to display it inside an existing view. I've already built a piece of code to launch an activity intent for reading my local PDF file, but of course, if no PDF Viewer app is already installed on the device, then nothing happens.
I've heard about APV, VuDroid, droidreader, etc but it seems that they all are APKs, not libraries that can be used inside my app code.
So, is there any real Android library to achieve this?
Thanks in advance.
This one you can try it which works in offline mode
https://github.com/bitfield66/PdfViewerAndroid_Offline
which just accepts pdf path.
Firstly to view a pdf in android you have to convert the pdf into images then display them to the user. (i am going to use a webview)
So to do this we need this library. It is my edited version of this git.
After you have imported the library into your project you need to create your activity.
The XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/webView1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
The java onCreate:
//Imports:
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.webkit.WebView;
import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFImage;
import com.sun.pdfview.PDFPage;
import com.sun.pdfview.PDFPaint;
import net.sf.andpdf.nio.ByteBuffer;
import net.sf.andpdf.refs.HardReference;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
//Globals:
private WebView wv;
private int ViewSize = 0;
//OnCreate Method:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Settings
PDFImage.sShowImages = true; // show images
PDFPaint.s_doAntiAlias = true; // make text smooth
HardReference.sKeepCaches = true; // save images in cache
//Setup webview
wv = (WebView)findViewById(R.id.webView1);
wv.getSettings().setBuiltInZoomControls(true);//show zoom buttons
wv.getSettings().setSupportZoom(true);//allow zoom
//get the width of the webview
wv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
ViewSize = wv.getWidth();
wv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
pdfLoadImages();//load images
}
Load Images:
private void pdfLoadImages()
{
try
{
// run async
new AsyncTask<Void, Void, Void>()
{
// create and show a progress dialog
ProgressDialog progressDialog = ProgressDialog.show(MainActivity.this, "", "Opening...");
#Override
protected void onPostExecute(Void result)
{
//after async close progress dialog
progressDialog.dismiss();
}
#Override
protected Void doInBackground(Void... params)
{
try
{
// select a document and get bytes
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/randompdf.pdf");
RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
ByteBuffer bb = ByteBuffer.NEW(channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()));
raf.close();
// create a pdf doc
PDFFile pdf = new PDFFile(bb);
//Get the first page from the pdf doc
PDFPage PDFpage = pdf.getPage(1, true);
//create a scaling value according to the WebView Width
final float scale = ViewSize / PDFpage.getWidth() * 0.95f;
//convert the page into a bitmap with a scaling value
Bitmap page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true);
//save the bitmap to a byte array
ByteArrayOutputStream stream = new ByteArrayOutputStream();
page.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
byte[] byteArray = stream.toByteArray();
//convert the byte array to a base64 string
String base64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
//create the html + add the first image to the html
String html = "<!DOCTYPE html><html><body bgcolor=\"#7f7f7f\"><img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>";
//loop through the rest of the pages and repeat the above
for(int i = 2; i <= pdf.getNumPages(); i++)
{
PDFpage = pdf.getPage(i, true);
page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true);
stream = new ByteArrayOutputStream();
page.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
byteArray = stream.toByteArray();
base64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
html += "<img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>";
}
html += "</body></html>";
//load the html in the webview
wv.loadDataWithBaseURL("", html, "text/html","UTF-8", "");
}
catch (Exception e)
{
Log.d("CounterA", e.toString());
}
return null;
}
}.execute();
System.gc();// run GC
}
catch (Exception e)
{
Log.d("error", e.toString());
}
}
I like the MuPDF Adnroid lib since it written in C++/NDK and it has unique features like clickable images (I mean an URL linked to the image) - met no other lib with this feature and I was really need it.
You actually can open PDF using no lib at all: using WebView via google docs but I don't like this way due to IC is required all the time while using MuPDF I can DL pdf file and freely open it offline any time. Also WebView way is more "hard" for device meaning battery draining + lags + CPU heating and it uses more trafic (if compared to DL&show way).
I'm working on a FTP-Client.
I've already created an FTP-Client based by this one: Android How to upload a file via FTP
With this code. It was possible to send a txt-File with an included string to my FTP-Server.
I've got pictures in my local folder "/sdcard/ftp/"
Now I'm trying to change the code, that it is possible that all the jpg-files in the folder will be send by ftp client.
package de.android.datenuebertragung;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPConnectionClosedException;
import org.apache.commons.net.ftp.FTPFile;
import android.app.Activity;
import android.util.Log;
public class FTPManager extends Activity{
FTPClient con = new FTPClient();{
try
{
con.connect("host");
if (con.login("user", "password"))
{
// in application never use hardcoded paths
File folder = new File("/sdcard/ftp/");
File tempFile = null;
FTPFile[] tempFTPFile = null;
//get all files in folder
for(String fileInDir : folder.list()){
tempFile = new File(fileInDir);
tempFTPFile = con.listNames(tempFile.getFiles);
if(tempFTPFile!=null || tempFTPFile.length<=0){
con.upload(fileInDir);
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
con.logout();
con.disconnect();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
I've got two errors in the these marked words (getFiles and upload):
tempFTPFile = con.listNames(tempFile.getFiles);
con.upload(fileInDir);
The error in con.listNames(tempFile.getFiles) is: getFiles cannot be resolved or is not a field
and the another error in con.upload(fileInDir) is: The method upload(String) is undefined for the type FTPClient
I've tried the whole day to solve this problem. Hope someone can help me. Maybe post the changed and worked code. I'm an absolutley newbie in Android programming.
If you've pasted your code directly and there isn't a typo then it should be getFiles() and not getFiles in this line...
tempFTPFile = con.listNames(tempFile.getFiles);
Also, I suspect the default transfer mode will be ASCII (this is usually the case for any FTP client software).
Try calling...
con.setFileType(FTP.BINARY_FILE_TYPE);
...before attempting the uploads.
Hej,
I have some data shipped out with the app which shall be copied on the external storage. It's nested in a couple of subfolders and I'd like to copy the whole structure.
I'm having a hard time getting a File object for any ressource in /assets. But I think I'm depended on that 'cause I need something like File.isDirectory() to determine if I have to start copying or dive deeper into the system.
My first approach was using Assets Manager but it seems that class is not providing the information I need. The most promising why was to obtain an AssetFileDescriptorand go down to a [FileDescriptor][2]. However non of them seems to have a isDirectory-method.
So my other approach is straight forward: Creating a File Object and be happy. However it seems like I'm running in this problem of lacking a proper path to instance the file object. I'm aware of file://android_asset but it doesn't seem to work for the fileconstructor.
My last idea would to utilise the InputStream (which I need for copying anyway) and somehow filter the byte for a significant bit which indicates this resource to be a directory. That's a pretty hacky solution and probably right in the hell of ineffectiveness but I don't see another way to get around that.
I had the same problem. At some point I realized that list() is really slow (50ms on every call), so i'm using a different approach now:
I have an (eclipse) ant-builder which creates an index-file everytime my asset-folder changes. The file just contains one file-name per line, so directories are listed implicitely (if they are not empty).
The Builder:
<?xml version="1.0"?>
<project default="createAssetIndex">
<target name="createAssetIndex">
<fileset id="assets.fileset" dir="assets/" includes="**"
excludes="asset.index" />
<pathconvert pathsep="${line.separator}" property="assets"
refid="assets.fileset">
<mapper>
<globmapper from="${basedir}/assets/*" to="*"
handledirsep="yes" />
</mapper>
</pathconvert>
<echo file="assets/asset.index">${assets}</echo>
</target>
</project>
The class which loads asset.index into a List of Strings, so you can do arbitrary stuff with it, fast:
import android.content.ContextWrapper;
import com.google.common.collect.ImmutableList;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* uses asset.index file (which is pregenerated) since asset-list()s take very long
*
*/
public final class AssetIndex {
//~ Static fields/initializers -------------------------------------------------------------------------------------
private static final Logger L = LoggerFactory.getLogger(AssetIndex.class);
//~ Instance fields ------------------------------------------------------------------------------------------------
private final ImmutableList<String> files;
//~ Constructors ---------------------------------------------------------------------------------------------------
public AssetIndex(final ContextWrapper contextWrapper) {
ImmutableList.Builder<String> ib = ImmutableList.builder();
L.debug("creating index from assets");
InputStream in = null;
Scanner scanner = null;
try {
in = contextWrapper.getAssets().open("asset.index");
scanner = new Scanner(new BufferedInputStream(in));
while (scanner.hasNextLine()) {
ib.add(scanner.nextLine());
}
scanner.close();
in.close();
} catch (final IOException e) {
L.error(e.getMessage(), e);
} finally {
if (scanner != null) {
scanner.close();
}
if (in != null) {
try {
in.close();
} catch (final IOException e) {
L.error(e.getMessage(), e);
}
}
}
this.files = ib.build();
}
//~ Methods --------------------------------------------------------------------------------------------------------
/* returns the number of files in a directory */
public int numFiles(final String dir) {
String directory = dir;
if (directory.endsWith(File.separator)) {
directory = directory.substring(0, directory.length() - 1);
}
int num = 0;
for (final String file : this.files) {
if (file.startsWith(directory)) {
String rest = file.substring(directory.length());
if (rest.charAt(0) == File.separatorChar) {
if (rest.indexOf(File.separator, 1) == -1) {
num = num + 1;
}
}
}
}
return num;
}
}
list() on AssetManager will probably give a null / zero length array / IOException if you try to get a list on a file, but a valid response on a directory.
But otherwise it should be file:///android_asset (with 3 /)
In my specific case, regular files have a name like filename.ext, while directories only have a name, without extension, and their name never contains the "." (dot) character.
So a regular file can be distinguished from a directory by testing its name as follows:
filename.contains(".")
If this your case too, the same solution should work for you.
hi i want to display my html image on android emulator, please help
package com.Htmlview;
import ja va.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.webkit.WebView;
public class Htmlview extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
WebView webview = new WebView(this);
setContentView(webview);
try {
String imageString="<html><body>" +
"<h2>Norwegian Mountain Trip</h2>" +
"<img src=\"C:/Users/Public/Pictures/Sample Pictures/pulpit.jpg\" alt=\"Pulpit rock\" width=\"304\" height=\"228\" /></body></html>";
AssetManager mgr = this.getAssets();
InputStream is = mgr.open("index3.html");
BufferedInputStream in = new BufferedInputStream(is); // read the contents of the file
webview.loadData(MessageFormat.format(imageString,arguments),"text/html", "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
}
}
You're never going to be able to access something on your workstation's hard drive from within Android. What you want to do is put the image into the assets folder in your Android app (which will then get bundled into the app) and link to it appropriately with file:///android_assets/. There are other ways of dealing with the issue, but that is the simplest.
I'm writing an app which will read XML from a webservice (probably via kSOAP2). I'm fairly happy with SAX parsing, as I've done XML parsing iPhone apps.
Unfortunately the webservice isn't public yet so for initial testing I have some files containing the XML I need to parse. In this early dev phase I just need to read the XML from the files and pass it into the XML parser
Xml.parse(this.testXML, root.getContentHandler());
How do I read the XML from a file/resource into a string to pass into this method. I want to crack on and test the parser, but this simple step is holding me up.
Thanks
Create a raw folder under res
Put your XML file in there, eg. testXML.xml:
/res/raw/testXML.xml
You should be able to use your XML parser using that as an inputstream:
Xml.parse(getResources().openRawResource(R.raw.testXML), Xml.Encoding.UTF_8, root.getContentHandler());
Try that.
I found a solution. Using Assets.
Here is the simple code example of how I did it.
I know I could have used XmlPullParser to simply load an xml file from res, but I wanted to use SAX parsing. This allows me to simply throw an XML string into the SAX parser for testing before I plug in the webservice.
It just uses a simple view with a Button to kick off the file load and a TextView to display the XML for now. I can get on with my parser :)
package com.martins.XmlParserTest
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class Main extends Activity {
Button btn;
TextView tvXml;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Load XML for parsing.
AssetManager assetManager = getAssets();
InputStream inputStream = null;
try {
inputStream = assetManager.open("textxml.xml");
} catch (IOException e) {
Log.e("tag", e.getMessage());
}
String s = readTextFile(inputStream);
TextView tv = (TextView)findViewById(R.id.textView1);
tv.setText(s);
}
});
}
private String readTextFile(InputStream inputStream) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte buf[] = new byte[1024];
int len;
try {
while ((len = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, len);
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
}
return outputStream.toString();
}
}
Raises exception due to incorrectly formed XML (line1,Pos0).
You tell parser that the encoding is UTF-8 and if it isn't you may get various errors (depending on parsers). If you are using non-xml editor to edit your XML it may save the file in a different encoding regardless what you declared it to be in the XML document.