I am trying to develop a simple application for download using DownloadManager but I need to do some changes, I want to download using ProgressbarDialog so how to do.
class DownloadReceiver
if(downloader == null) return;
long completeId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
if(completeId == downloadTaskId){
Query query = new Query();
query.setFilterById(downloadTaskId);
Cursor cur = downloader.query(query);
if (cur.moveToFirst()) {
int columnIndex = cur.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == cur.getInt(columnIndex)) {
//Download the task has been completed, remove
new VersionPersistent(context).clear();
String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
File apkFile = new File(Uri.parse(uriString).getPath());
Intent installIntent = new Intent();
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
installIntent.setAction(Intent.ACTION_VIEW);
installIntent.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive");
context.startActivity(installIntent);
} else {
Toast.makeText(context, R.string.download_failure, Toast.LENGTH_SHORT).show();
}
}
cur.close();
and also
download and install
if ( latestVersion == null || !isNetworkActive() ) return;
downloader = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Query query = new Query();
query.setFilterById(downloadTaskId);
Cursor cur = downloader.query(query);
// Download tasks already exists
if(cur.moveToNext()) return;
DownloadManager.Request task = new DownloadManager.Request(Uri.parse(latestVersion.targetUrl));
String apkName = extractName(latestVersion.targetUrl);
String title = String.format("%s - v%s", apkName,latestVersion.name);
task.setTitle(title);
task.setDescription(latestVersion.feature);
task.setVisibleInDownloadsUi(true);
task.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
task.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkName);
downloadTaskId = downloader.enqueue(task);
Thanks :)
USE this class to show progress bar , this will give you an idea for downloading an image.
DownloadImageTask.java
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
/** Reference to the view which should receive the image */
private final WeakReference imageRef;
public DownloadImageTask(ImageView imageView) {
imageRef = new WeakReference(imageView);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(DownloadImageActivity.this, "Wait", "Downloading...");
}
#Override
protected Bitmap doInBackground(String... params) {
InputStream input = null;
try {
URL url = new URL(params[0]);
// We open the connection
URLConnection conection = url.openConnection();
conection.connect();
input = new BufferedInputStream(url.openStream(), 8192);
// we convert the inputStream into bitmap
bitmap = BitmapFactory.decodeStream(input);
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return bitmap;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(Bitmap bitmap) {
progressDialog.dismiss();
if (isCancelled()) {
bitmap = null;
}
if (imageRef != null) {
ImageView imageView = imageRef.get();
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
} else
Toast.makeText(DownloadImageActivity.this, "Error while downloading the image!", Toast.LENGTH_LONG).show();
}
}
}
give permission in AndroidMenifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
you want using progressDialog, does that mean you don't need to download in the background ?
My solution is:
using AsyncTask
init the profressDialog before you call task.execute()
then show the dialog in onPreExecute
download file doInBackfround
update progess in onProgressUpdate
and dosomething you want when download complete in onPostExecute
you can learn AsyncTask and HttpURLConnection and IO Stream
You should use DownloadManager's
DownloadManager.query(DownloadManager.Query)
This gives you a Cursor to browse the columns COLUMN_TOTAL_SIZE_BYTES (Total size of the download in bytes) and COLUMN_BYTES_DOWNLOADED_SO_FAR (Number of bytes download so far).
With this information, you'll have the details to update the ProgressBarDialog.
Use Asynctask for this. Try this.
private class DownloadFileTask extends AsyncTask<String, Void, String> {
ProgressDialog pd;
#Override
protected String doInBackground(String... params) {
// Your File Download Code here
}
#Override
protected void onPostExecute(String result) {
pd.dismiss();
}
#Override
protected void onPreExecute() {
pd = new ProgressDialog(yourActivity.this);
pd.setMessage("Please Wait...");
pd.show();
}
#Override
protected void onProgressUpdate(Void... values) {}
}
}
This is my working sample code. I use SeekBar instead of ProgressBar. Hope this help
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.downloadmanager" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_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=".MainActivity">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<SeekBar
android:id="#+id/seekBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<LinearLayout
style="?android:buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal">
<Button
android:id="#+id/buttonStartDownload"
style="?android:buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="startDownload"
android:text="Start" />
<Button
android:id="#+id/buttonCancelDownload"
style="?android:buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="cancelDownload"
android:text="Cancel" />
<Button
android:id="#+id/buttonViewDownloads"
style="?android:buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="viewDownloads"
android:text="View" />
</LinearLayout>
</RelativeLayout>
MainActivity.java:
package com.example.downloadmanager;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private DownloadManager mDownloadManager;
private long mDownloadReference;
private TextView mTextView;
private SeekBar mSeekBar;
private static Cursor mCursor;
private static boolean mDownloading = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textView);
mSeekBar = (SeekBar) findViewById(R.id.seekBar);
// Set filter to only when download is complete and register broadcast receiver
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(downloadReceiver, filter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, 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();
// noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void startDownload(View view) {
mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse("http://192.168.0.100/files/test.txt");
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
// Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
// Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(false);
// Set the title of this download, to be displayed in notifications (if enabled).
request.setTitle("My Download");
// Set a description of this download, to be displayed in notifications (if enabled)
request.setDescription("Android Data download using DownloadManager...");
// Set the local destination for the downloaded file to a path within the application's external files directory
request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "test.txt");
// Enqueue a new download and same the referenceId
mDownloadReference = mDownloadManager.enqueue(request);
new Thread(new Runnable() {
#Override
public void run() {
mDownloading = true;
while (mDownloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(mDownloadReference);
mCursor = mDownloadManager.query(q);
if (mCursor != null && mCursor.getCount() > 0) {
mCursor.moveToFirst();
int bytes_downloaded = mCursor.getInt(mCursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytes_total = mCursor.getInt(mCursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (mCursor.getInt(mCursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
mDownloading = false;
}
final double dl_progress = ((bytes_downloaded * 100) / bytes_total);
runOnUiThread(new Runnable() {
#Override
public void run() {
mSeekBar.setProgress((int) dl_progress);
}
});
}
if (mCursor != null) {
mCursor.close();
}
}
}
}).start();
}
public void cancelDownload(View view) {
mDownloading = false;
if (mDownloadManager != null) {
mDownloadManager.remove(mDownloadReference);
}
mSeekBar.setProgress(0);
}
public void viewDownloads(View view) {
Intent i = new Intent();
i.setAction(DownloadManager.ACTION_VIEW_DOWNLOADS);
startActivity(i);
}
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (mDownloadReference == referenceId) {
Uri uri = mDownloadManager.getUriForDownloadedFile(mDownloadReference);
if (uri != null) {
String mimeType = mDownloadManager.getMimeTypeForDownloadedFile(mDownloadReference);
File file = new File(uri.getPath());
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("FileName", file.getName());
jsonObject.put("FilePath", file.getAbsolutePath());
jsonObject.put("FileSize", file.length());
jsonObject.put("MimeType", mimeType);
String msg = "Download completed! \n\n" + jsonObject.toString(5);
mTextView.setText(msg);
} catch (JSONException e) {
mTextView.setText(e.getMessage());
}
}
}
}
};
}
Related
I followed the istructions of the tutorial at com.google.codelab.mlkit.
Instead of using intent.data I am using FileProvider to get and analyze the full picture.
I replaced the virtural image in the emulation based on the recommendation in Android emulator camera custom image.
So I start my app (main activity), take a photo with the internal camera (which is the replaced virtual image) and get back to the main activity. I run into the code recognizeTextFromImage(), but I never run into .addOnSuccessListener() and .addOnFailureListener(). That surpises me because I even do not get a failure. Nothing is printed into the log.
I am using API-level 23 because the resultCode is 0 (instead of -1) if I am using a higher API.
My question is: why doesn't my code run into .addOnSuccessListener() or at least into .addOnFailureListener() ?
1. Update
I tried "intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);``` and this changed the behavior. It took seconds to read the file. So I think #Danish was correct that the file was not created by the camera. But: same issue with addOnFailureListener(). Maybe the file is to big? Or did I send the wrong format? The Log says "W/e.codelab.mlki: Verification of java.lang.String com.google.codelab.mlkit.MainActivity.recognizeTextFromImage(com.google.mlkit.vision.common.InputImage) took 536.238ms"
2. Update
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="Pictures" />
</paths>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.codelab.mlkit">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature
android:name="android.hardware.camera"
android:required="true"/>
<queries>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
</queries>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity"
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.codelab.mlkit.vision.DEPENDENCIES"
android:value="ocr" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths">
</meta-data>
</provider>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="#xml/activity_main_scene"
tools:context=".MainActivity" >
<TableLayout
android:layout_width="360dp"
android:layout_height="539dp"
android:layout_centerInParent="true">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView_ServiceID"
android:layout_width="11dp"
android:layout_height="match_parent"
android:layout_weight="0.3"
android:gravity="center"
android:text="ServiceID"
android:textAlignment="viewStart" />
<EditText
android:id="#+id/editText_ServiceID"
android:layout_height="match_parent"
android:layout_weight="0.7
"
android:gravity="left"
android:inputType="text"
android:text="4711" />
</TableRow>
</TableLayout>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="359dp"
android:layout_height="match_parent">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView_Site"
android:layout_height="match_parent"
android:layout_weight="0.3"
android:gravity="center"
android:text="Site"
android:textAlignment="viewStart" />
<Spinner
android:id="#+id/spinner_Site"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<ImageButton
android:id="#+id/imageButton_Site"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/ic_photo" />
<EditText
android:id="#+id/editText_Site"
android:layout_height="match_parent"
android:layout_weight="0.6"
android:inputType="text"
android:text="not yet reconized" />
</TableRow>
</TableLayout>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="end" >
<TableRow
android:layout_gravity="end"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageButton
android:id="#+id/imageButton6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/ic_send" />
<ImageButton
android:id="#+id/imageButton7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/ic_save" />
</TableRow>
</TableLayout>
</TableRow>
</TableLayout>
</RelativeLayout>
package com.google.codelab.mlkit;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private static final String TAG = "MainActivity";
private ImageButton imageButton_Site;
private EditText editText_Site;
private Spinner spinner_Site;
private InputImage createdImage;
String recognizedText = "";
String currentPhotoPath;
static final int REQUEST_IMAGE_CAPTURE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageButton_Site = findViewById(R.id.imageButton_Site);
imageButton_Site.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dispatchTakePictureIntent();
}
});
spinner_Site = findViewById(R.id.spinner_Site);
String[] items = new String[]{"Chicago", "New York"}; // has to be retrieved from server based on GPS (satellite)
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, items);
spinner_Site.setAdapter(adapter);
spinner_Site.setOnItemSelectedListener(this);
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Toast.makeText(getApplicationContext(), "Error occurred while creating the File!",Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
BuildConfig.APPLICATION_ID + ".fileprovider",
photoFile);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
takePictureIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
takePictureIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // new
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult( requestCode, resultCode, data);
// Log.d("OLR", "onActivityResult: "+ requestCode +" "+resultCode+" "+data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bitmap bitmap=BitmapFactory.decodeFile(currentPhotoPath);
Bitmap imagebitmap=Bitmap.createBitmap(bitmap);//Just add this line and everything will work fine.I tried this code, its working like a charm.
int check = bitmap.getWidth();
InputImage inputImage = InputImage.fromBitmap(imagebitmap, 0);
String text = recognizeTextFromImage(inputImage);
if (text.isEmpty())
{
Toast.makeText(getApplicationContext(), "Nothing recognized. Please try again!",Toast.LENGTH_LONG).show();
editText_Site.setText("Failed !");
}
else {
editText_Site.setText(text);
}
}
else {
Toast.makeText(getApplicationContext(), "An issue occurred. Please inform app owner!",Toast.LENGTH_LONG).show();
}
}
private File createImageFile() throws IOException {
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
// create directory if necessary
if (!storageDir.exists()){
storageDir.mkdir();
}
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",Locale.GERMANY).format(new Date());
String imageFileName = "OLR_" + timeStamp + "_";
File image = File.createTempFile(
imageFileName, // prefix
".jpg", // suffix
storageDir // directory
);
// imageFile = image;
currentPhotoPath = image.getAbsolutePath();
return image;
}
private String recognizeTextFromImage(InputImage image) {
TextRecognizer recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS);
Task<Text> task = recognizer.process(image);
// recognizer.process(image)
task
.addOnSuccessListener(
new OnSuccessListener<Text>() {
#Override
public void onSuccess(Text texts) {
recognizedText = processTextRecognitionResult(texts);
Log.d(TAG,"Successful");
}
})
/*.addOnSuccessListener(
new OnSuccessListener<Text>() {
#Override
public void onSuccess(Text texts) {
recognizedText = texts.getText();
editText_Site.setText(recognizedText);
Log.d(TAG,"Successful");
}
})*/
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
e.printStackTrace();
Log.d(TAG,"Not Successful");
}
});
recognizer.close();
return recognizedText;
}
private String processTextRecognitionResult(Text texts) {
String recognizedText = "";
List<Text.TextBlock> blocks = texts.getTextBlocks();
if (blocks.size() == 0) {
// No text found
}
else {
for (int i = 0; i < blocks.size(); i++) {
List<Text.Line> lines = blocks.get(i).getLines();
for (int j = 0; j < lines.size(); j++) {
List<Text.Element> elements = lines.get(j).getElements();
for (int k = 0; k < elements.size(); k++) {
String elementText = elements.get(k).getText();
recognizedText = recognizedText + elementText;
}
}
}
}
return recognizedText;
}
private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
spinner_Site = findViewById(R.id.spinner_Site);
editText_Site = findViewById(R.id.editText_Site);
editText_Site.setText(spinner_Site.getSelectedItem().toString());
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing
}
}
Problem solved
(1) I had to add intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
(2) I checked the the returned string "recognizedText" which was always empty, because the thread executed after the variable was filled. Ashes on my head. My thanks go to #Danish who gave me the decisive hint to add logs to the right place.
(3) For any reason I had to wait sometime before starting debugging.
Worked for hours on this and Alhamdulillah I came out with the solution.
#Micky I found bugs in your code.So to help you out I am providing you with solution below. Basically,the bug is related to rotation if the image is not captured in landscape mode the ocr did not recognized the text properly so its necessary to make sure that the image is rotated properly before scanning.There is also the problem in this line recognizedText = processTextRecognitionResult(texts); it doesnt recognize the text properly you can check below I have added one more edittext to show you the difference on how the text send by texts.getText() gives you better result.
Check the code below:
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.text.Text;
import com.google.mlkit.vision.text.TextRecognition;
import com.google.mlkit.vision.text.TextRecognizer;
import com.google.mlkit.vision.text.latin.TextRecognizerOptions;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private static final String TAG = "MainActivity";
private ImageButton imageButton_Site;
private EditText editText_Site;
EditText editText;
private Spinner spinner_Site;
private InputImage createdImage;
String recognizedText="";
String currentPhotoPath;
static final int REQUEST_IMAGE_CAPTURE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText_Site=findViewById(R.id.editText_Site);
editText=findViewById(R.id.editText);
imageButton_Site = findViewById(R.id.imageButton_Site);
spinner_Site = findViewById(R.id.spinner_Site);
String[] items = new String[]{"Chicago", "Ludwigshafen"}; // has to be retrieved from server based on GPS (satellite)
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, items);
spinner_Site.setAdapter(adapter);
spinner_Site.setOnItemSelectedListener(this);
imageButton_Site.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dispatchTakePictureIntent();
}
});
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Toast.makeText(getApplicationContext(), "Error occurred while creating the File!",Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,BuildConfig.APPLICATION_ID+".fileprovider",
photoFile);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult( requestCode, resultCode, data);
// Log.d("OLR", "onActivityResult: "+ requestCode +" "+resultCode+" "+data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
ParcelFileDescriptor parcelFileDescriptor = null;
try {
parcelFileDescriptor = getContentResolver().openFileDescriptor(Uri.fromFile(new File(currentPhotoPath)), "r");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
ExifInterface exifInterface = null;
try {
exifInterface = new ExifInterface(fileDescriptor);
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
Matrix matrix = new Matrix();
matrix.setRotate(90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
Matrix matrixe = new Matrix();
matrixe.setRotate(180);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrixe, true);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
Matrix matrixes = new Matrix();
matrixes.setRotate(270);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrixes, true);
break;
case ExifInterface.ORIENTATION_NORMAL:
Matrix matrix12 = new Matrix();
matrix12.setRotate(ExifInterface.ORIENTATION_ROTATE_90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix12, true);
}
InputImage inputImage=null;
inputImage= InputImage.fromBitmap(bitmap,0);
String text=null;
try {
text = recognizeTextFromImage(inputImage);
} catch (IOException e) {
e.printStackTrace();
}
if (text.isEmpty())
{
Toast.makeText(getApplicationContext(), "Nothing recognized. Please try again!",Toast.LENGTH_LONG).show();
editText_Site.setText("Failed !");
}
else {
editText_Site.setText(text);
}
}
else {
Toast.makeText(getApplicationContext(), "An issue occurred. Please inform app owner!",Toast.LENGTH_LONG).show();
}
}
private File createImageFile() throws IOException {
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
// create directory if necessary
if (!storageDir.exists()){
storageDir.mkdir();
}
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.GERMANY).format(new Date());
String imageFileName = "OLR_" + timeStamp + "_";
File image = File.createTempFile(
imageFileName, // prefix
".jpg", // suffix
storageDir // directory
);
// imageFile = image;
currentPhotoPath = image.getAbsolutePath();
return image;
}
private String recognizeTextFromImage(InputImage image) throws IOException {
TextRecognizer recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS);
Task<Text> task = recognizer.process(image)
.addOnSuccessListener(
new OnSuccessListener<Text>() {
#Override
public void onSuccess(Text texts) {
recognizedText = processTextRecognitionResult(texts);
editText.setText(texts.getText());
Log.d(TAG,"Successful");
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
e.printStackTrace();
Log.d(TAG,"Not Successful");
}
});
return recognizedText;
}
private String processTextRecognitionResult(Text texts) {
String recognizedText = "";
List<Text.TextBlock> blocks = texts.getTextBlocks();
if (blocks.size() == 0) {
// No text found
}
else {
for (int i = 0; i < blocks.size(); i++) {
List<Text.Line> lines = blocks.get(i).getLines();
for (int j = 0; j < lines.size(); j++) {
List<Text.Element> elements = lines.get(j).getElements();
for (int k = 0; k < elements.size(); k++) {
String elementText = elements.get(k).getText();
recognizedText = recognizedText + elementText;
}
}
}
}
return recognizedText;
}
private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
spinner_Site = findViewById(R.id.spinner_Site);
editText_Site.setText(spinner_Site.getSelectedItem().toString());
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing
}
}
I'm working on an app where the user can fill out a report card and send it through the email client of choice (Gmail in my case). In addition to text, the user needs to be able to attach one or more images, but I can't seem to get it to work (full code attached further down).
Below is the onActivityResult which attaches the images to the view and puts their Uris in "userSelectedImageUriList". This seems to work.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode==REQUEST_CODE_BROWSE_PICTURE)
{
if(resultCode==RESULT_OK)
{
// Get return image uri. If select the image from camera the uri like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
// If select the image from gallery the uri like content://media/external/images/media/1316970.
Uri fileUri = data.getData();
// Save user choose image file uri in list.
if(userSelectedImageUriList == null)
{
userSelectedImageUriList = new ArrayList<Uri>();
}
userSelectedImageUriList.add(fileUri);
// Create content resolver.
ContentResolver contentResolver = getContentResolver();
try {
// Open the file input stream by the uri.
InputStream inputStream = contentResolver.openInputStream(fileUri);
// Get the bitmap.
Bitmap imgBitmap = BitmapFactory.decodeStream(inputStream);
ImageView imageview = new ImageView(ReportCard.this);
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.imageHolderLayout);
LinearLayout.LayoutParams params = new LinearLayout
.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
// Add image path from drawable folder.
imageview.setImageBitmap(imgBitmap);
imageview.setLayoutParams(params);
linearLayout.addView(imageview);
inputStream.close();
}catch(FileNotFoundException ex)
{
Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
}catch(IOException ex)
{
Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
}
}
}
}
Next, when the user clicks the send button I create the email intent.
public void sendReport(Context context) {
EditText nameField = (EditText)findViewById(R.id.EditTextName);
EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
EditText dateField = (EditText)findViewById(R.id.EditTextDate);
EditText bodyField = (EditText)findViewById(R.id.EditTextBody);
if(!nameField.getText().toString().matches("") && !emailField.getText().toString().matches("") && !locationField.getText().toString().matches("") && !dateField.getText().toString().matches("") && !bodyField.getText().toString().matches("")) {
PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_email", emailField.getText().toString()).commit();
PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_name", nameField.getText().toString()).commit();
String emailBody = "Name: "+nameField.getText()+"\n\n";
emailBody += "Location: "+locationField.getText()+"\n\n";
emailBody += "Time: "+dateField.getText()+"\n\n";
emailBody += "Description: "+bodyField.getText();
Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
// set the type to 'email'
emailIntent.setType("text/plain");
String to[] = {emailField.getText().toString()};
emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
// the attachment
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, userSelectedImageUriList);
// the mail
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Report");
emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody);
startActivity(Intent.createChooser(emailIntent , "Send using..."));
finish();
} else {
Toast.makeText(this, getString(R.string.field_error), Toast.LENGTH_SHORT).show();
}
}
Now, this is where things stop working. The chooser is displayed but the images are not attached. Gmail opens but a toast is displayed with "Could not attach file".
Full code
ReportCard.java
package com.zaewin.reports;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
public class ReportCard extends Activity {
long reportID;
long newRowId;
// Log tag that is used to distinguish log info.
private final static String TAG_BROWSE_PICTURE = "BROWSE_PICTURE";
// Used when request action Intent.ACTION_GET_CONTENT
private final static int REQUEST_CODE_BROWSE_PICTURE = 1;
// Used when request read external storage permission.
private final static int REQUEST_PERMISSION_READ_EXTERNAL = 2;
// Save user selected image uri list.
private ArrayList<Uri> userSelectedImageUriList = null;
// Currently displayed user selected image index in userSelectedImageUriList.
private int currentDisplayedUserSelectImageIndex = 0;
#Override
public void onBackPressed() {
saveReport(ReportCard.this);
finish();
}
// create an action bar button
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.reportmenu, menu);
return super.onCreateOptionsMenu(menu);
}
// handle button activities
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.deleteButton:
new AlertDialog.Builder(this)
.setTitle(R.string.delete)
.setMessage(R.string.delete_prompt)
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Bundle bundle = getIntent().getExtras();
Boolean deletestatus = deleteReport(getApplicationContext(), bundle.getInt("reportID"));
if(deletestatus == true) {
CharSequence text = getString(R.string.delete_success);
Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
toast.show();
finish();
} else {
CharSequence text = getString(R.string.delete_fail);
Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
toast.show();
}
}})
.setNegativeButton(android.R.string.no, null).show();
return true;
case R.id.saveButton:
saveReport(getApplicationContext());
return true;
case R.id.sendButton:
sendReport(getApplicationContext());
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.report_view);
setTitle(R.string.report_card);
Bundle bundle = getIntent().getExtras();
if(bundle != null) {
reportID = bundle.getInt("reportID");
loadReport(reportID);
} else {
setDefaults();
}
final Button button = (Button) findViewById(R.id.buttonAddPicture);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Because camera app returned uri value is something like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
// So if show the camera image in image view, this app require below permission.
int readExternalStoragePermission = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE);
if(readExternalStoragePermission != PackageManager.PERMISSION_GRANTED)
{
String requirePermission[] = {Manifest.permission.READ_EXTERNAL_STORAGE};
ActivityCompat.requestPermissions(ReportCard.this, requirePermission, REQUEST_PERMISSION_READ_EXTERNAL);
}else {
openPictureGallery();
}
}
});
}
/* Invoke android os system file browser to select images. */
private void openPictureGallery()
{
// Create an intent.
Intent openAlbumIntent = new Intent();
// Only show images in the content chooser.
// If you want to select all type data then openAlbumIntent.setType("*/*");
// Must set type for the intent, otherwise there will throw android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT }
openAlbumIntent.setType("image/*");
// Set action, this action will invoke android os browse content app.
openAlbumIntent.setAction(Intent.ACTION_GET_CONTENT);
// Start the activity.
startActivityForResult(openAlbumIntent, REQUEST_CODE_BROWSE_PICTURE);
}
/* When the action Intent.ACTION_GET_CONTENT invoked app return, this method will be executed. */
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode==REQUEST_CODE_BROWSE_PICTURE)
{
if(resultCode==RESULT_OK)
{
// Get return image uri. If select the image from camera the uri like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
// If select the image from gallery the uri like content://media/external/images/media/1316970.
Uri fileUri = data.getData();
// Save user choose image file uri in list.
if(userSelectedImageUriList == null)
{
userSelectedImageUriList = new ArrayList<Uri>();
}
userSelectedImageUriList.add(fileUri);
// Create content resolver.
ContentResolver contentResolver = getContentResolver();
try {
// Open the file input stream by the uri.
InputStream inputStream = contentResolver.openInputStream(fileUri);
// Get the bitmap.
Bitmap imgBitmap = BitmapFactory.decodeStream(inputStream);
ImageView imageview = new ImageView(ReportCard.this);
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.imageHolderLayout);
LinearLayout.LayoutParams params = new LinearLayout
.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
// Add image path from drawable folder.
imageview.setImageBitmap(imgBitmap);
imageview.setLayoutParams(params);
linearLayout.addView(imageview);
inputStream.close();
}catch(FileNotFoundException ex)
{
Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
}catch(IOException ex)
{
Log.e(TAG_BROWSE_PICTURE, ex.getMessage(), ex);
}
}
}
}
/* After user choose grant read external storage permission or not. */
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode==REQUEST_PERMISSION_READ_EXTERNAL)
{
if(grantResults.length > 0)
{
int grantResult = grantResults[0];
if(grantResult == PackageManager.PERMISSION_GRANTED)
{
// If user grant the permission then open choose image popup dialog.
openPictureGallery();
}else
{
Toast.makeText(getApplicationContext(), "You denied read external storage permission.", Toast.LENGTH_LONG).show();
}
}
}
}
public void setDefaults() {
EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
emailField.setText(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("report_email", ""), TextView.BufferType.EDITABLE);
EditText nameField = (EditText)findViewById(R.id.EditTextName);
nameField.setText(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("report_name", ""), TextView.BufferType.EDITABLE);
Calendar c = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String formattedDate = df.format(c.getTime());
EditText dateField = (EditText)findViewById(R.id.EditTextDate);
dateField.setText(formattedDate, TextView.BufferType.EDITABLE);
}
public void loadReport(long reportID) {
ReportDbHelper mDbHelper = new ReportDbHelper(getBaseContext());
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
ReportContract.ReportEntry._ID,
ReportContract.ReportEntry.COLUMN_NAME,
ReportContract.ReportEntry.COLUMN_EMAIL,
ReportContract.ReportEntry.COLUMN_LOCATION,
ReportContract.ReportEntry.COLUMN_DATE,
ReportContract.ReportEntry.COLUMN_BODY
};
// Filter results WHERE "title" = 'My Title'
String selection = ReportContract.ReportEntry._ID + " = ?";
String[] selectionArgs = { Long.toString(reportID) };
// How you want the results sorted in the resulting Cursor
String sortOrder = ReportContract.ReportEntry.COLUMN_NAME + " DESC";
Cursor cursor = db.query(
ReportContract.ReportEntry.TABLE_NAME, // The table to query
projection, // The columns to return
selection, // The columns for the WHERE clause
selectionArgs, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);
//List itemIds = new ArrayList<>();
while(cursor.moveToNext()) {
EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
emailField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_EMAIL)), TextView.BufferType.EDITABLE);
EditText nameField = (EditText)findViewById(R.id.EditTextName);
nameField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_NAME)), TextView.BufferType.EDITABLE);
EditText dateField = (EditText)findViewById(R.id.EditTextDate);
dateField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_DATE)), TextView.BufferType.EDITABLE);
EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
locationField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_LOCATION)), TextView.BufferType.EDITABLE);
EditText bodyField = (EditText)findViewById(R.id.EditTextBody);
bodyField.setText(cursor.getString(cursor.getColumnIndexOrThrow(ReportContract.ReportEntry.COLUMN_BODY)), TextView.BufferType.EDITABLE);
}
cursor.close();
db.close();
}
public long saveReport(Context context) {
EditText nameField = (EditText)findViewById(R.id.EditTextName);
EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
EditText dateField = (EditText)findViewById(R.id.EditTextDate);
EditText bodyField = (EditText)findViewById(R.id.EditTextBody);
ReportDbHelper mDbHelper = new ReportDbHelper(context);
SQLiteDatabase db = mDbHelper.getWritableDatabase();
// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(ReportContract.ReportEntry.COLUMN_NAME, nameField.getText().toString());
values.put(ReportContract.ReportEntry.COLUMN_EMAIL, emailField.getText().toString());
values.put(ReportContract.ReportEntry.COLUMN_LOCATION, locationField.getText().toString());
values.put(ReportContract.ReportEntry.COLUMN_DATE, dateField.getText().toString());
values.put(ReportContract.ReportEntry.COLUMN_BODY, bodyField.getText().toString());
CharSequence text;
try {
if(reportID == 0) {
newRowId = db.insert(ReportContract.ReportEntry.TABLE_NAME, null, values);
text = getString(R.string.save_success);
} else {
String where = ReportContract.ReportEntry._ID + " = ?";
String[] whereArgs = new String[]{String.valueOf(reportID)};
newRowId = db.update(ReportContract.ReportEntry.TABLE_NAME, values, where, whereArgs);
text = getString(R.string.update_success);
}
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
toast.show();
//finish();
} catch(android.database.sqlite.SQLiteException ex) {
text = getString(R.string.save_error);
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
toast.show();
}
db.close();
return newRowId;
}
public boolean deleteReport(Context context, Integer reportID) {
ReportDbHelper mDbHelper = new ReportDbHelper(context);
SQLiteDatabase db = mDbHelper.getWritableDatabase();
Boolean status = db.delete(ReportContract.ReportEntry.TABLE_NAME, ReportContract.ReportEntry._ID + "=" + reportID, null) > 0;
db.close();
return status;
}
public void sendReport(Context context) {
EditText nameField = (EditText)findViewById(R.id.EditTextName);
EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
EditText dateField = (EditText)findViewById(R.id.EditTextDate);
EditText bodyField = (EditText)findViewById(R.id.EditTextBody);
if(!nameField.getText().toString().matches("") && !emailField.getText().toString().matches("") && !locationField.getText().toString().matches("") && !dateField.getText().toString().matches("") && !bodyField.getText().toString().matches("")) {
PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_email", emailField.getText().toString()).commit();
PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_name", nameField.getText().toString()).commit();
String emailBody = "Ditt namn: "+nameField.getText()+"\n\n";
emailBody += "Plats: "+locationField.getText()+"\n\n";
emailBody += "Tidpunkt: "+dateField.getText()+"\n\n";
emailBody += "Beskrivning: "+bodyField.getText();
Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
ArrayList<Uri> uris = new ArrayList<Uri>();
for (Uri file : userSelectedImageUriList)
{
File fileIn = new File(file.toString());
fileIn.setReadable(true, false);
Uri u = Uri.fromFile(fileIn);
uris.add(u);
}
// set the type to 'email'
emailIntent.setType("text/plain");
String to[] = {emailField.getText().toString()};
emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
// the attachment
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
// the mail
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Rapport från Hamnarbetarappen");
emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody);
startActivity(Intent.createChooser(emailIntent , "Skicka med..."));
finish();
} else {
Toast.makeText(this, getString(R.string.field_error), Toast.LENGTH_SHORT).show();
}
}
}
report_view.xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/ScrollView01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:scrollbars="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp">
<EditText
android:id="#+id/EditTextName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/report_name"
android:inputType="textPersonName" >
</EditText>
<EditText
android:id="#+id/EditTextEmail"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/report_email"
android:inputType="textEmailAddress" >
</EditText>
<EditText
android:id="#+id/EditTextLocation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/report_location" >
</EditText>
<EditText
android:id="#+id/EditTextDate"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/report_date"
android:inputType="datetime" >
</EditText>
<EditText
android:id="#+id/EditTextBody"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/report_description"
android:inputType="textMultiLine"
android:lines="5" >
</EditText>
<LinearLayout
android:id="#+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="5dp">
<Button
android:id="#+id/buttonAddPicture"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/blue_button"
android:drawableRight="#drawable/ic_action_camera"
android:padding="10dp"
android:text="#string/report_takepicture"
android:textAlignment="center"
android:textColor="#color/actionbar_text" />
</LinearLayout>
<LinearLayout
android:id="#+id/imageHolderLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="5dp">
</LinearLayout>
</ScrollView>
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zaewin.reports" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="22" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="true" />
<uses-permission android:name="android.permission.INTERNET" android:required="true"/>
<application android:theme="#style/CustomActionBarTheme" android:label="#string/app_name" android:icon="#mipmap/ic_launcher" android:allowBackup="true">
<activity android:label="ReportCard" android:screenOrientation="portrait" android:configChanges="orientation|keyboardHidden" android:name=".ReportCard">
<meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".ReportList" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
</application>
</manifest>
I've solved it. When the images are chosen they are put into the ArrayList "userSelectedImageUriList" in onActivityResult.
Instead of parsing this list in the sendReport method, I just add this list to the intent.
The working method looks like this:
public void sendReport(Context context) {
EditText nameField = (EditText)findViewById(R.id.EditTextName);
EditText emailField = (EditText)findViewById(R.id.EditTextEmail);
EditText locationField = (EditText)findViewById(R.id.EditTextLocation);
EditText dateField = (EditText)findViewById(R.id.EditTextDate);
EditText bodyField = (EditText)findViewById(R.id.EditTextBody);
if(!nameField.getText().toString().matches("") && !emailField.getText().toString().matches("") && !locationField.getText().toString().matches("") && !dateField.getText().toString().matches("") && !bodyField.getText().toString().matches("")) {
PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_email", emailField.getText().toString()).apply();
PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit().putString("report_name", nameField.getText().toString()).apply();
String emailBody = "Name: "+nameField.getText()+"\n\n";
emailBody += "Location: "+locationField.getText()+"\n\n";
emailBody += "Time: "+dateField.getText()+"\n\n";
emailBody += "Description: "+bodyField.getText();
Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
// set the type to 'email'
emailIntent.setType("text/plain");
String to[] = {emailField.getText().toString()};
emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
// the attachment - ArrayList populated in onActivityResult
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, userSelectedImageUriList);
// the mail
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Report);
emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody);
startActivity(Intent.createChooser(emailIntent , "Send with..."));
//finish();
} else {
Toast.makeText(this, getString(R.string.field_error), Toast.LENGTH_SHORT).show();
}
}
I have an application where I am recording audio in an activity. User has a start recording and stop recording button to do that. Once user clicks the stop recording button, it sends the recorded mp3 file to server (encoded string) and server process it and a response is received. I want to do the following tasks:
Since this process is long, I want to do this in a separate thread(preferably).
The process of sending and receiving response is to be shown using progress bar.
User should be able to navigate to other screens while he is waiting(i.e. current activity may be destroyed)
I tried using Toast messages before and after the function where I send mp3 to server. But there is no sync, sometimes msg comes early, sometime it's late. That's why a proper progress bar is required.How to do this? Can AsyncTask be used with what I want to achieve in (3). or should I use some other form of multithreading. Please help.Below is the activity
(Please ignore the indentations, I couldn't fix the code on stack-overflow:
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class RecordActivity extends AppCompatActivity {
private static final String LOG_TAG = "AudioRecordTest";
private static String msg = "default";
public final static String Result_MESSAGE = "in.innovatehub.ankita_mehta.tinyears.ResultMESSAGE";
private static final int REQUESTCODE_RECORDING = 109201;
private Button mRecorderApp = null;
private static String mFileName = "music.mp3";
private static String mFilePath = String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/TinyEars/"));
private MediaRecorder mRecorder = null;
private MediaPlayer mPlayer = null;
private ImageButton mRecordImageButton = null;
private ImageButton mPlayImageButton = null;
boolean mStartRecording = true;
boolean mStartPlaying = true;
private Button mShowStatsButton = null;
private static final String TAG = "RecordActivity";
private Handler handler = new Handler();
final Runnable updater = new Runnable() {
public void run() {
handler.postDelayed(this, 1);
if(mRecorder!=null) {
int maxAmplitude = mRecorder.getMaxAmplitude();
if (maxAmplitude != 0) {
// visualizerView.addAmplitude(maxAmplitude);
}
}
else{
}
}
};
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFilePath+"/"+mFileName);
mPlayer.prepare();
mPlayer.start();
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
Log.i("Completion Listener", "Song Complete");
stopPlaying();
mRecordImageButton.setEnabled(true);
}
});
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
if (mPlayer != null) {
mPlayer.reset();
mPlayer.release();
mPlayer = null;
mPlayImageButton.setImageResource(R.drawable.playicon);
// mStartPlaying = true;
} else {
mPlayImageButton.setImageResource(R.drawable.pauseicon);
// mStartPlaying = false;
}
}
private void startRecording() {
AudioRecordTest(String.valueOf(System.currentTimeMillis()));
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorder.setOutputFile(mFilePath+"/"+mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
try {
mRecorder.start();
Toast.makeText(getApplicationContext(), "Recording started", Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e(LOG_TAG, "start() failed");
}
}
private void stopRecording() {
if (mRecorder != null) {
mRecorder.stop();
mRecorder.release();
Toast.makeText(getApplicationContext(), "Audio recorded successfully",Toast.LENGTH_LONG).show();
mRecorder = null;
mRecordImageButton.setImageResource(R.drawable.micicon);
// mStartRecording = true;
} else {
mRecordImageButton.setImageResource(R.drawable.stopicon);
// mStartRecording = false;
}
}
public void AudioRecordTest(String text) {
boolean exists = (new File(mFilePath+"/"+mFileName)).exists();
if (!exists) {
new File(mFileName).mkdirs();
}
// mFileName += "audiorecordtest.mp3";
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record);
Log.d(TAG,"HERE IS FILE PATH"+mFilePath+"/"+mFileName);
mRecordImageButton = (ImageButton) findViewById(R.id.imageButton2);
mPlayImageButton = (ImageButton) findViewById(R.id.imageButton3);
mShowStatsButton = (Button) findViewById(R.id.showMeStats);
mRecorderApp = (Button) findViewById(R.id.recorderApp);
AudioRecordTest("00000");
mRecordImageButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
onRecord(mStartRecording);
if (mStartRecording) {
mRecordImageButton.setImageResource(R.drawable.stopicon);
mPlayImageButton.setEnabled(false);
//setText("Stop recording");
} else {
mRecordImageButton.setImageResource(R.drawable.micicon);
mPlayImageButton.setEnabled(true);
mShowStatsButton.setEnabled(true);
mShowStatsButton.setVisibility(View.VISIBLE);
Toast.makeText(getApplicationContext(),"Hold on... we are getting the results!",Toast.LENGTH_SHORT).show();
pressedSavBtn();
Toast.makeText(getApplicationContext(),"Parsing done ... now you may see the results!",Toast.LENGTH_SHORT).show();
//setText("Start recording");
}
mStartRecording = !mStartRecording;
}
});
mPlayImageButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
onPlay(mStartPlaying);
if (mStartPlaying) {
mPlayImageButton.setImageResource(R.drawable.pauseicon);
mRecordImageButton.setEnabled(false);
mShowStatsButton.setEnabled(false);
//setText("Stop playing");
} else {
mPlayImageButton.setImageResource(R.drawable.playicon);
mRecordImageButton.setEnabled(true);
mShowStatsButton.setEnabled(false);
//setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
});
//Calling recorder ...
mRecorderApp.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
if (isAvailable(getApplicationContext(), intent)) {
startActivityForResult(intent, REQUESTCODE_RECORDING);
}
}
});
mShowStatsButton = (Button) findViewById(R.id.showMeStats);
mShowStatsButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
sendResults(msg);
}
});
}
public void pressedSavBtn(){
try {
thread.start();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
mShowStatsButton.setVisibility(View.VISIBLE);
}
}
public void writeToFile(String data)
{
// Get the directory for the user's public pictures directory.
final File path = new File(mFilePath+"/");
// Make sure the path directory exists.
if(!path.exists())
{
// Make it, if it doesn't exit
path.mkdirs();
}
final File file = new File(path, "config.txt");
// Save your stream, don't forget to flush() it before closing it.
try
{
file.createNewFile();
FileOutputStream fOut = new FileOutputStream(file);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(data);
myOutWriter.close();
fOut.flush();
fOut.close();
}
catch (IOException e)
{
Log.e("Exception", "File write failed: " + e.toString());
}
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append((line + "\n"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
//THIS IS FILE ENCODING CODE
File file = new File(mFilePath+"/"+mFileName);
byte[] bytes = FileUtils.readFileToByteArray(file);
String encoded = Base64.encodeToString(bytes, 0);
Log.d("~~~~~~~~ Encoded: ", encoded);
writeToFile(encoded);
//THIS IS URL CONN CODE
String link = "http://192.168.50.0:9000/divide_result";
URL url = new URL(link);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(link);
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("Name", "StackOverFlow"));
nameValuePairs.add(new BasicNameValuePair("Date", encoded));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
String sb = convertStreamToString(response.getEntity().getContent());
Log.d(TAG,"MESSAGE NOW"+sb);
Log.d(TAG, sb);
msg = sb.toString();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
public void sendResults(String res){
Log.d(TAG, "Inside on create, Navigating to Result Screen Activity!");
Intent intent = new Intent(getApplicationContext(), ResultsScreenActivity.class);
intent.putExtra(Result_MESSAGE, res);
startActivity(intent);
}
public static boolean isAvailable(Context ctx, Intent intent) {
final PackageManager mgr = ctx.getPackageManager();
List<ResolveInfo> list = mgr.queryIntentActivities(intent,PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUESTCODE_RECORDING) {
if (resultCode == RESULT_OK) {
Uri audioUri = intent.getData();
// make use of this MediaStore uri
// e.g. store it somewhere
}
else {
// react meaningful to problems
}
}
else {
super.onActivityResult(requestCode,
resultCode, intent);
}
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
thread.stop();
}
#Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(updater);
if(mRecorder!=null) {
mRecorder.stop();
mRecorder.reset();
mRecorder.release();
}
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
handler.post(updater);
}
}
Also below is the layout-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:id="#+id/activity_record"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|center_horizontal"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:screenOrientation="portrait"
android:orientation="vertical"
tools:context="in.innovatehub.mobile.ankita_mehta.tinyears.RecordActivity">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/linearLayout_record"
android:orientation="vertical"
android:gravity="center">
<ImageButton
android:id="#+id/imageButton2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:scaleType="fitXY"
android:src="#drawable/micicon" />
<ImageButton
android:id="#+id/imageButton3"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:scaleType="fitXY"
android:src="#drawable/playicon" />
<Button
android:id="#+id/showMeStats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:visibility="gone"
android:onClick="loadStats"
android:text="#string/showMeStats" />
<Button
android:id="#+id/recorderApp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:gravity="center"
android:text="#string/UseRecorderApp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/loadStatsLinearLayout"
android:gravity="center"
android:visibility="gone"
android:orientation="vertical">
<TextView
android:id="#+id/loadingMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/loadingMessage"
/>
<ProgressBar
android:id="#+id/downloadProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
/>
</LinearLayout>
</LinearLayout>
You can use an IntentService to upload your content to the server. By default, it runs on a seperate thread and is not activity bound. Then use a broadcast receiver to communicate the result back to any activity. You can find an example here.
For the progress bar, you can create a notification and show the progress bar there, this will not block your application's UI.
For hitting the server at you should use AsyncTask or Runnable thread, without disturb the main tread
for custome progress dialog use the following code
xml file.
<?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"
android:orientation="horizontal"
android:background="#color/color_white"
android:padding="5dp" >
<ProgressBar
android:id="#+id/layCustomContentProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/layCustomProgressHeading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/layCustomProgressInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</LinearLayout>
and the method
public Dialog getCustomPogressDialog(Context context, String heading, String text) {
// Declare the customer dialog
Dialog dlgProgress = new Dialog(context);
// Set no title for the dialog
dlgProgress.requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set the content view to the customer_alert layout
dlgProgress.setContentView(R.layout.layout_custom_process_progress);
// Cancel the dialog when touched outside.
dlgProgress.setCanceledOnTouchOutside(false);
// Set the main heading
TextView dlgHeading = (TextView) dlgProgress.findViewById(R.id.layCustomProgressHeading);
dlgHeading.setText(heading);
// set the info
TextView dlgInfo = (TextView) dlgProgress.findViewById(R.id.layCustomProgressInfo);
dlgInfo.setText(text);
// Return the refenrece to the dialog
return dlgProgress;
}
I am new to android studio and learning to develop the android apps,
I have got an error as stated above and am unable to resolve it.
Any kind of help will be appreciated.
Thank you!!
My ledControl.java code is as follow
package com.led.led;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.os.AsyncTask;
import java.io.IOException;
import java.util.UUID;
public class ledControl extends ActionBarActivity {
Button btnOn, btnOff, btnDis;
SeekBar brightness;
TextView lumn;
String address = null;
private ProgressDialog progress;
BluetoothAdapter myBluetooth = null;
BluetoothSocket btSocket = null;
private boolean isBtConnected = false;
//SPP UUID. Look for it
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent newint = getIntent();
address = newint.getStringExtra(DeviceList.EXTRA_ADDRESS); //receive the address of the bluetooth device
//view of the ledControl
setContentView(R.layout.activity_led_control);
//call the widgtes
btnOn = (Button)findViewById(R.id.button2);
btnOff = (Button)findViewById(R.id.button3);
btnDis = (Button)findViewById(R.id.button4);
brightness = (SeekBar)findViewById(R.id.seekBar);
lumn = (TextView)findViewById(R.id.lumn);
new ConnectBT().execute(); //Call the class to connect
//commands to be sent to bluetooth
btnOn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
turnOnLed(); //method to turn on
}
});
btnOff.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
turnOffLed(); //method to turn off
}
});
btnDis.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Disconnect(); //close connection
}
});
brightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser==true)
{
lumn.setText(String.valueOf(progress));
try
{
btSocket.getOutputStream().write(String.valueOf(progress).getBytes());
}
catch (IOException e)
{
}
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
private void Disconnect()
{
if (btSocket!=null) //If the btSocket is busy
{
try
{
btSocket.close(); //close connection
}
catch (IOException e)
{ msg("Error");}
}
finish(); //return to the first layout
}
private void turnOffLed()
{
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("TF".toString().getBytes());
}
catch (IOException e)
{
msg("Error");
}
}
}
private void turnOnLed()
{
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("TO".toString().getBytes());
}
catch (IOException e)
{
msg("Error");
}
}
}
// fast way to call Toast
private void msg(String s)
{
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_led_control, 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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class ConnectBT extends AsyncTask<Void, Void, Void> // UI thread
{
private boolean ConnectSuccess = true; //if it's here, it's almost connected
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(ledControl.this, "Connecting...", "Please wait!!!"); //show a progress dialog
}
#Override
protected Void doInBackground(Void... devices) //while the progress dialog is shown, the connection is done in background
{
try
{
if (btSocket == null || !isBtConnected)
{
myBluetooth = BluetoothAdapter.getDefaultAdapter();//get the mobile bluetooth device
BluetoothDevice dispositivo = myBluetooth.getRemoteDevice(address);//connects to the device's address and checks if it's available
btSocket = dispositivo.createInsecureRfcommSocketToServiceRecord(myUUID);//create a RFCOMM (SPP) connection
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
btSocket.connect();//start connection
}
}
catch (IOException e)
{
ConnectSuccess = false;//if the try failed, you can check the exception here
}
return null;
}
#Override
protected void onPostExecute(Void result) //after the doInBackground, it checks if everything went fine
{
super.onPostExecute(result);
if (!ConnectSuccess)
{
msg("Connection Failed. Is it a SPP Bluetooth? Try again.");
finish();
}
else
{
msg("Connected.");
isBtConnected = true;
}
progress.dismiss();
}
}
}
And the activity_led_control.xml is as below
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context="com.led.led.ledControl">
<TextView android:text="LED Control" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textview2" />
<SeekBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/seekBar"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Brightness"
android:id="#+id/textView3"
android:layout_above="#+id/seekBar"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ON"
android:id="#+id/button2"
android:layout_above="#+id/button3"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OFF"
android:id="#+id/button3"
android:layout_above="#+id/button4"
android:layout_alignLeft="#+id/button2"
android:layout_alignStart="#+id/button2" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disconnect"
android:id="#+id/button4"
android:layout_above="#+id/textView3"
android:layout_alignLeft="#+id/button3"
android:layout_alignStart="#+id/button3" />
</RelativeLayout>
I know that this error is in text field statement but i dont know how to resolve it ?
You have no TextView identified by lumn in your activity_led_control.xml.
Therefore this line doesn't compile :
lumn = (TextView)findViewById(R.id.lumn);
since R.id.lumn is not generated.
You have TextViews identified by "#+id/textview2" and "#+id/textview3". If you rename one of them to "#+id/lumn", your code will compile.
Because you dont have a TextView with id lumn in your layout
I'm trying to run a my project on the android emulator, the project doesn't have errors, the reference to Facebook SDK was added. But, when i run the application it shows a "onerror" message ..
please anyone can execute my code and tell me the problems (or) give me the solutions
MainActivity.java
package com.example.simplelogin1;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.Util;
import com.facebook.android.AsyncFacebookRunner.RequestListener;
import com.facebook.android.Facebook.DialogListener;
import com.facebook.android.FacebookError;
public class MainActivity extends Activity implements OnClickListener
{
ImageView button,userImage;
TextView textName;
Button btnShowAccessTokens;
ListView listv;
String FILENAME = "AndroidSSO_data";
String imageURL = "";
String name = "";
String userName = "";
String gender = "";
String _error;
String access_token;
private AsyncFacebookRunner mAsyncRunner=null;
private SharedPreferences mPrefs;
Facebook fb=null;
ArrayList<String> friends_list;
Boolean Connectiontimeout = false;
Bitmap profilePic;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String APP_ID="650535718332424"; //****************************APP_ID************************************
fb=new Facebook(APP_ID);
mAsyncRunner = new AsyncFacebookRunner(fb);
friends_list = new ArrayList<String>();
btnShowAccessTokens = (Button) findViewById(R.id.btn_show_access_tokens);
button=(ImageView) findViewById(R.id.login);
listv=(ListView) findViewById(R.id.listView1);
userImage = (ImageView) findViewById(R.id.imageView1);
textName = (TextView) findViewById(R.id.textView1);
button.setOnClickListener(this);
updateButtonImage();
//***************************Access Token Button*****************************************
btnShowAccessTokens.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
showAccessTokens();
}
});
}
public void showAccessTokens()
{
String access_token = fb.getAccessToken();
Toast.makeText(getApplicationContext(),"Access Token: " + access_token, Toast.LENGTH_LONG).show();
}
//***********************************************************************************
//*****************************Login and Logout Image Button*****************************
private void updateButtonImage()
{
if(fb.isSessionValid())
{
button.setImageResource(R.drawable.logout_button);
}else
{
button.setImageResource(R.drawable.login_button);
}
}
//***************************************************************************************
//**************************Login Onclick Method*****************************************
#Override
public void onClick(View v)
{
if(fb.isSessionValid())
{
//*****************Logout********************
try{
fb.logout(getApplicationContext());
updateButtonImage();
userImage.setVisibility(View.INVISIBLE);
textName.setVisibility(View.INVISIBLE);
btnShowAccessTokens.setVisibility(View.INVISIBLE);
listv.setVisibility(View.INVISIBLE);
}catch (MalformedURLException e)
{
e.printStackTrace();
}catch (IOException e)
{
e.printStackTrace();
}
//************************************************************
}else
{
//**********************Login**********************************
mPrefs = getPreferences(MODE_PRIVATE);
String access_token = mPrefs.getString("access_token", null);
long expires = mPrefs.getLong("access_expires", 0);
if (access_token != null)
{
fb.setAccessToken(access_token);
// Making show access tokens button visible
//btnShowAccessTokens.setVisibility(View.VISIBLE);
//listv.setVisibility(View.VISIBLE);
Log.d("FB Sessions", "" + fb.isSessionValid());
}
if (expires != 0)
{
fb.setAccessExpires(expires);
}
{
fb.authorize(this,new String[] {"email","publish_stream"} , new DialogListener()
{
#Override
public void onFacebookError(FacebookError e)
{
Toast.makeText(MainActivity.this, "fbError", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(DialogError e)
{
Toast.makeText(MainActivity.this, "onError", Toast.LENGTH_SHORT).show();
}
#Override
public void onComplete(Bundle values)
{
updateButtonImage();
// Function to handle complete event Edit Preferences and update facebook acess_token
SharedPreferences.Editor editor = mPrefs.edit();
editor.putString("access_token",fb.getAccessToken());
editor.putLong("access_expires",fb.getAccessExpires());
editor.commit();
//getting user profile
try {
JSONObject me = new JSONObject(fb.request("me"));
new getFacebookData().execute();
} catch (MalformedURLException e)
{
e.printStackTrace();
} catch (JSONException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
//getting users Friend list
mAsyncRunner.request("me/friends", new FriendsRequestListener());
Toast.makeText(getApplicationContext(), "Success ", Toast.LENGTH_LONG).show();
userImage.setVisibility(View.VISIBLE);
textName.setVisibility(View.VISIBLE);
btnShowAccessTokens.setVisibility(View.VISIBLE);
listv.setVisibility(View.VISIBLE);
}
#Override
public void onCancel()
{
Toast.makeText(MainActivity.this, "onCancel", Toast.LENGTH_SHORT).show();
}
});
}
}
}
//***************************************onActivityResult********************************************
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
fb.authorizeCallback(requestCode, resultCode, data);
}
//***********************************getting users Friend list Function*******************************
private class FriendsRequestListener implements RequestListener
{
String friendData;
//Method runs when request is complete
public void onComplete(String response, Object state)
{
Log.v("", "FriendListRequestONComplete");
//Create a copy of the response so i can be read in the run() method.
friendData = response;
Log.v("friendData--", ""+friendData);
//Create method to run on UI thread
MainActivity.this.runOnUiThread(new Runnable()
{
public void run()
{
try
{
//Parse JSON Data
JSONObject json;
json = Util.parseJson(friendData);
//Get the JSONArry from our response JSONObject
JSONArray friendArray = json.getJSONArray("data");
Log.v("friendArray--", ""+friendArray);
for(int i = 0; i< friendArray.length(); i++)
{
JSONObject frnd_obj = friendArray.getJSONObject(i);
friends_list.add(frnd_obj.getString("name")+"~~~"+frnd_obj.getString("id"));
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1,android.R.id.text1, friends_list);
listv.setAdapter(adapter);
} catch (JSONException e)
{
e.printStackTrace();
} catch (FacebookError e)
{
e.printStackTrace();
}
}
});
}
#Override
public void onIOException(IOException e, Object state)
{
}
#Override
public void onFileNotFoundException(FileNotFoundException e,Object state)
{
}
#Override
public void onMalformedURLException(MalformedURLException e,Object state)
{
}
#Override
public void onFacebookError(FacebookError e, Object state)
{
}
}
//**********************************************************************************************
//**************Async class for getting facebook data in background thread**********************
public class getFacebookData extends AsyncTask<String, Void, String>
{
ProgressDialog pd = null;
#Override
protected void onPreExecute(){
pd = ProgressDialog.show(MainActivity.this, "Please wait","Loading please wait..", true);
pd.setCancelable(true);
}
#Override
protected String doInBackground(String... params){
fbUserProfile();
return null;
}
#Override
protected void onPostExecute(String result){
pd.dismiss();
if (Connectiontimeout != true)
{
textName.setText(name);
userImage.setImageBitmap(profilePic);
} else {
Toast.makeText(MainActivity.this, "Connection Time out",Toast.LENGTH_SHORT).show();
}
}
}
//**********************************************************************************************************
//**********************getting user facebook data from facebook server****************************************
public void fbUserProfile()
{
try{
access_token = mPrefs.getString("access_token", null);
JSONObject jsonObj = null;
JSONObject jsonObjData = null;
JSONObject jsonObjUrl = null;
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 50000);
HttpConnectionParams.setSoTimeout(httpParameters, 50000);
HttpClient client = new DefaultHttpClient(httpParameters);
String requestURL = "https://graph.facebook.com/me?fields=picture,id,name&access_token="+ access_token;
Log.i("Request URL:", "---" + requestURL);
HttpGet request = new HttpGet(requestURL);
HttpResponse response = client.execute(request);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String webServiceInfo = "";
while ((webServiceInfo = rd.readLine()) != null)
{
Log.i("Service Response:", "---" + webServiceInfo);
jsonObj = new JSONObject(webServiceInfo);
jsonObjData = jsonObj.getJSONObject("picture");
jsonObjUrl = jsonObjData.getJSONObject("data");
name = jsonObj.getString("name");
userName = jsonObj.getString("username");
gender = jsonObj.getString("gender");
imageURL = jsonObjUrl.getString("url");
profilePic = BitmapFactory.decodeStream((InputStream) new URL(imageURL).getContent());
}
} catch (Exception e)
{
Connectiontimeout = true;
}
}
//***********************************************************************************************************
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/login_button"/>
<Button
android:id="#+id/btn_show_access_tokens"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Token"
android:visibility="invisible" />
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#+id/btn_show_access_tokens"
android:visibility="invisible">
</ListView>
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/login"
android:src="#drawable/ic_launcher"
android:visibility="invisible" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/listView1"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/btn_show_access_tokens"
android:layout_toRightOf="#+id/imageView1"
android:text="Name"
android:visibility="invisible"/>
</RelativeLayout>
manifest.file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.simplelogin1"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.simplelogin1.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
in my drawable folder:
login_button
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- When selected -->
<item android:drawable="#drawable/login"
android:state_selected="true" />
<!-- When not selected-->
<item android:drawable="#drawable/login_down" />
</selector>
logout_button
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- When selected -->
<item android:drawable="#drawable/logout"
android:state_selected="true" />
<!-- When not selected-->
<item android:drawable="#drawable/logout_down" />
</selector>
my logcat:
12-26 15:07:01.189: D/Facebook-WebView(8330): Webview loading URL: https://m.facebook.com/dialog/oauth?display=touch&client_id=650535718332424&scope=email%2Cpublish_stream&type=user_agent&redirect_uri=fbconnect%3A%2F%2Fsuccess
12-26 15:07:01.309: D/Facebook-authorize(8330): Login failed: com.facebook.android.DialogError: The connection to the server was unsuccessful.
12-26 15:07:01.329: D/Facebook-WebView(8330): Webview loading URL: https://m.facebook.com/dialog/oauth?display=touch&client_id=650535718332424&scope=email%2Cpublish_stream&type=user_agent&redirect_uri=fbconnect%3A%2F%2Fsuccess
please anyone can help me...