I am programming an application inside Android studio. Now I want my application to never close and work as a cycle. I know I can do that with the Intent class and configure the Manifest.xml file for all the activities that are inside my application.
But to print I go outside of my application to get to a printpreview with the printsettings. At this moment - when the printing is finished - that preview will close and go back (automatically) to my last activity (the one that comes before the printpreview). Now instead of going to that previous activity, I want to go back to the startpage (category.LAUNCHER).
But that doesn't work with programming with the Intent class because there is no xml file of the printpreview. Because it is a method which creates a bitmapfile and goes outside of my application to print.
/**
* Method which creates a bitmap of the picture with the Odisee logo and
* goes to the printpreviewpage with settings.
*
*/
private void doPhotoPrint() {
try {
//Creates object from PrintHelper class
PrintHelper photoPrinter = new PrintHelper(this);
//Scales image
photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FILL);
// Find the last picture
String[] projection = new String[]{
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE};
final Cursor cursor = getApplicationContext().getContentResolver()
.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null,
null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
String imageLocation = null;
if (cursor.moveToFirst()) {
imageLocation = cursor.getString(1);
}
File imageFile = new File(imageLocation);
//Creates bitmapfile to print
if (imageFile.exists()) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//Gets the resources (last taken picture + Odisee logo)
Bitmap bitmap = BitmapFactory.decodeFile(imageLocation);
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(),R.drawable.logo_odisee2);
Bitmap bmOverlay = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
//Draws the Odisee logo onto the picture
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bitmap, new Matrix(),null);
canvas.drawBitmap(bitmap2,950,550,null);
//Sets printer orientation to landscape
photoPrinter.setOrientation(PrintHelper.ORIENTATION_LANDSCAPE);
//Goes to screen to print the bitmap
photoPrinter.printBitmap("photobooth", bmOverlay);
}
}catch (Exception e) {
System.err.println("Fout!");
}
}
If I create an Intent object it will either skip the printpreview part or crash after being printed. So I am wondering if there is another possible way to fix this issue and keep the application running?
<activity android:name=".startPagina">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Related
I am currently using android-demo-app/ObjectDetection/ On Temi Robot, the preloaded images are working so far but when I press "live" to go to live object detection screen, it is rotated 90 degrees to the right.
Temi robot only have a front facing camera on the same side of the screen.
I have tried changing textureView.setTransform() imageAnalysisConfig.Builder().setTargetRotation() imageAnalysis.setTargetRotation() but to no avail
Also tried changing AndroidManifest.xml screenOrientation under activity tag to fullSenor or Landscape but nothing changed.
I have been looking up and down on the Android Developer CameraX page for an answer first link second link but I can't find any. Maybe I am not smart enough to find the solution here.
Any help is much appreciated!
AbstactCameraXActivity.java
private void setupCameraX() {
final TextureView textureView = getCameraPreviewTextureView();
final PreviewConfig previewConfig = new PreviewConfig.Builder().build();
final Preview preview = new Preview(previewConfig);
// Matrix m = new Matrix();
// m.postRotate(180);
// textureView.setTransform(m); //not working
preview.setOnPreviewOutputUpdateListener(output -> textureView.setSurfaceTexture(output.getSurfaceTexture()));
final var imageAnalysisConfig =
new ImageAnalysisConfig.Builder()
.setTargetResolution(new Size(500, 500))
.setCallbackHandler(mBackgroundHandler)
.setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
//.setTargetRotation(Surface.ROTATION_0) // not working
.build();
imageAnalysis = new ImageAnalysis(imageAnalysisConfig);
imageAnalysis.setAnalyzer((image, rotationDegrees) -> {
if (SystemClock.elapsedRealtime() - mLastAnalysisResultTime < 500) {
return;
}
final R2 result = analyzeImage(image, rotationDegrees);
if (result != null) {
mLastAnalysisResultTime = SystemClock.elapsedRealtime();
runOnUiThread(() -> applyToUiAnalyzeImageResult(result));
}
});
//imageAnalysis.setTargetRotation(Surface.ROTATION_180); // not working
CameraX.bindToLifecycle(this, preview, imageAnalysis);
}
ObjectDetectionActivity.java
#Override
#WorkerThread
#Nullable
protected AnalysisResult analyzeImage(ImageProxy image, int rotationDegrees) {
try {
if (mModule == null) {
mModule = LiteModuleLoader.load(MainActivity.assetFilePath(getApplicationContext(), "yolov5s.torchscript.ptl"));
}
} catch (IOException e) {
Log.e("Object Detection", "Error reading assets", e);
return null;
}
Bitmap bitmap = imgToBitmap(Objects.requireNonNull(image.getImage()));
Matrix matrix = new Matrix();
matrix.postRotate(90.0f);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, PrePostProcessor.mInputWidth, PrePostProcessor.mInputHeight, true);
final Tensor inputTensor = TensorImageUtils.bitmapToFloat32Tensor(resizedBitmap, PrePostProcessor.NO_MEAN_RGB, PrePostProcessor.NO_STD_RGB);
IValue[] outputTuple = mModule.forward(IValue.from(inputTensor)).toTuple();
final Tensor outputTensor = outputTuple[0].toTensor();
final float[] outputs = outputTensor.getDataAsFloatArray();
float imgScaleX = (float)bitmap.getWidth() / PrePostProcessor.mInputWidth;
float imgScaleY = (float)bitmap.getHeight() / PrePostProcessor.mInputHeight;
float ivScaleX = (float)mResultView.getWidth() / bitmap.getWidth();
float ivScaleY = (float)mResultView.getHeight() / bitmap.getHeight();
final ArrayList<Result> results = PrePostProcessor.outputsToNMSPredictions(outputs, imgScaleX, imgScaleY, ivScaleX, ivScaleY, 0, 0);
return new AnalysisResult(results);
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.pytorch.demo.objectdetection">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<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:configChanges="orientation"
android:screenOrientation="fullSensor">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ObjectDetectionActivity"
android:configChanges="orientation"
android:screenOrientation="fullSensor">
</activity>
</application>
</manifest>
Update
I think I may know the problem now. In ObjectDetectionActivity's setupCameraX() method, I should manipulate the textureView and manupilating the pivot of the matrix transform is what I need. I began to see some of the cameraView on screen. However I don't know what is the x and y needed in this parameter...
final TextureView textureView = getCameraPreviewTextureView();
final PreviewConfig previewConfig = new PreviewConfig.Builder().build();
final Preview preview = new Preview(previewConfig);
Matrix m = new Matrix();
m.postRotate(180,x,y);//potential solution here.
textureView.setTransform(m); //not working
preview.setOnPreviewOutputUpdateListener(output -> textureView.setSurfaceTexture(output.getSurfaceTexture()));
I have changed the cameraX version to 1.0.0 from 1.0.0-alpha5
private void setupCameraX() {
ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
PreviewView previewView = getCameraPreviewTextureView();
final Preview preview = new Preview.Builder()
.setTargetRotation(Surface.ROTATION_270)//working nicely
.build();
//TODO: Check if result_view can render over preview_view
CameraSelector cameraSelector = new CameraSelector
.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_FRONT)
.build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
executor = Executors.newSingleThreadExecutor();
imageAnalysis = new ImageAnalysis.Builder()
.setTargetResolution(new Size(500, 500))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
imageAnalysis.setAnalyzer(executor,
image -> {
Log.d("image analyzer","Entered Analyse method");
if (SystemClock.elapsedRealtime() - mLastAnalysisResultTime < 500) {
return;
}
final T result = analyzeImage(image, 90);
if (result != null) {
mLastAnalysisResultTime = SystemClock.elapsedRealtime();
runOnUiThread(() -> applyToUiAnalyzeImageResult(result));
}
});
camera = cameraProvider.bindToLifecycle(
this,
cameraSelector,
imageAnalysis,
preview);
} catch (InterruptedException | ExecutionException e) {
new AlertDialog
.Builder(this)
.setTitle("Camera setup error")
.setMessage(e.getMessage())
.setPositiveButton("Ok",
(dialog, which) -> {
})
.show();
}
}, ContextCompat.getMainExecutor(this));
Note: getCameraPreviewTextureView() is methods that inflate a ViewStub. I am just following a pytorch android example.
#Override
protected PreviewView getCameraPreviewTextureView() {
mResultView = findViewById(R.id.resultView);
//
return ((ViewStub) findViewById(R.id.preview_view_stub))
.inflate()
.findViewById(R.id.preview_view);
}
I am trying to make payment using ATH Movil. So it needs to open the ATH Movil app and get the response from it either completed or cancel. After launching the ATH Movil app and getting the response, it is creating a new activity every time instead of coming back to the same activity which launched the app.
private static void execute(Context context, String json, long timeout) {
PackageInfo athmInfo;
int athmVersionCode = 0;
String athmBundleId = COM_EVERTEC_ATHMOVIL_ANDROID + buildType;
Intent intent = context.getPackageManager().getLaunchIntentForPackage(athmBundleId);
try {
athmInfo = context.getPackageManager().getPackageInfo(athmBundleId, 0);
athmVersionCode = athmInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
logForDebug(e.getMessage());
}
if (intent == null || athmVersionCode <= ConstantUtil.ATH_MOVIL_REQUIRED_VERSION_CODE) {
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(ConstantUtil.ATH_MOVIL_MARKET_URL));
}
intent.putExtra((ConstantUtil.BUNDLE), context.getPackageName());
intent.putExtra(ConstantUtil.JSON_DATA_KEY, json);
intent.putExtra(ConstantUtil.PAYMENT_DURATION_TIME_KEY, timeout);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
}
here is the manifest file:
<activity
android:name=".Activity1"
android:label=""
android:screenOrientation="portrait">
<intent-filter>
<action android:name="....ATHMSDK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Also Activity1 implements PaymentResponseListener and onResume of Activity1 I am calling
PaymentResponse.validatePaymentResponse(getIntent(), Activity1.this); // this function is from their sdk and is read only.
Now when Activity1 launches the ATH Movil app and get the response. It creating again creating Activity1 instead of coming back to the existing one. Can somebody help me? What is wrong with my code?
Add this to your Activity tag in AndroidManifesto:
android:launchMode="singleTop"
This assumes that you want to navigate back to the same Task that started the ATH Movil and the last item on the back stack was indeed Activity1. As long as these conditions hold true, then android OS will return you to the same instance of Activity1.
For more information on this, you can also refer to this.
I need to share image and add "Save image" item in android share menu, I saw something like this in 9gag app, they have "Save" item in share menu, and share menu seems to be a bottom sheet. But how it can be achieved?
What I've done:
I added empty activity with intent filter in manifest which launches service and this service downloads image
<activity
android:name=".model.services.ShareActivity"
android:icon="#drawable/download_icon"
android:label="Save">
<intent-filter
android:label="Save"
android:icon="#drawable/download_icon">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*"/>
</intent-filter>
</activity>
and now I have this icon in share menu and it works, but this icon also appear in share menu of other apps, I need to show it only in my app, how I can make it private or something?
Ok, I found a solution. First - we need activity which will handle image saving intent, this activity can launch service or something. I make it like this:
public class ShareActivity extends Activity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
String url = extras.getString("url");
String name = extras.getString("name");
String description = extras.getString("description");
SaveImageService.downloadFile(url, name, description);
finish();
}
}
Where SaveImageService has static method which handle image saving to SD card
Second, we need to add some text in manifest:
<activity
android:name=".model.services.ShareActivity"
android:icon="#drawable/download_icon"
android:label="Save">
<intent-filter
android:label="Save"
android:icon="#drawable/download_icon">
<action android:name="com.my_app.random_text.SAVE_IMAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*"/>
</intent-filter>
</activity>
Here intent filter has custom action (this is important) this custom action is just some string, not app package or something (I'm using package name just because I like it).
Next, we need to add this activity to share menu list:
this will get bitmap Uri for sharing in other apps from ImageView
// Returns the URI path to the Bitmap displayed in specified ImageView
static public Uri getLocalBitmapUri(ImageView imageView) {
// Extract Bitmap from ImageView drawable
Drawable drawable = imageView.getDrawable();
Bitmap bmp = null;
if (drawable instanceof BitmapDrawable) {
bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
} else {
return null;
}
// Store image to default external storage directory
Uri bmpUri = null;
try {
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "share_image_" + System.currentTimeMillis() + ".png");
file.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.JPEG, 80, out);
out.close();
bmpUri = Uri.fromFile(file);
} catch (IOException e) {
e.printStackTrace();
}
return bmpUri;
}
And this will collect all apps that can share image plus our save image intent
public void shareExcludingApp(Context ctx, PhotoView snapImage) {
// Get access to the URI for the bitmap
Uri bmpUri = ShareTool.getLocalBitmapUri(snapImage);
if (bmpUri == null) return;
List<Intent> targetedShareIntents = new ArrayList<>();
//get all apps which can handle such intent
List<ResolveInfo> resInfo = ctx.getPackageManager().queryIntentActivities(createShareIntent(bmpUri), 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
Intent targetedShare = createShareIntent(bmpUri);
//add all apps excluding android system and ourselves
if (!info.activityInfo.packageName.equals(getContext().getPackageName())
&& !info.activityInfo.packageName.contains("com.android")) {
targetedShare.setPackage(info.activityInfo.packageName);
targetedShare.setClassName(
info.activityInfo.packageName,
info.activityInfo.name);
targetedShareIntents.add(targetedShare);
}
}
}
//our local save feature will appear in share menu, intent action SAVE_IMAGE in manifest
Intent targetedShare = new Intent("com.my_app.random_text.SAVE_IMAGE"); //this is that string from manifest!
targetedShare.putExtra(Intent.EXTRA_STREAM, bmpUri);
targetedShare.setType("image/*");
targetedShare.setPackage(getContext().getPackageName());
targetedShare.putExtra("url", iSnapViewPresenter.getSnapUrlForSave());
targetedShare.putExtra("name", iSnapViewPresenter.getSnapNameForSave());
targetedShare.putExtra("description", iSnapViewPresenter.getSnapDescriptionForSave());
targetedShareIntents.add(targetedShare);
//collect all this intents in one list
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0),
"Share Image");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
ctx.startActivity(chooserIntent);
}
I'm developing an Android application to capture screenshots. What I'm trying to do is make a service with a button on the top of the screen and taking screenshot by tapping it.
I wonder if it may work, with service as I said. Also I want the button excluded from the screenshot. Am I able to do this?
Here is the code that allowed my screenshot to be stored on sd card and used later for whatever your needs are:
First, add proper permission to save file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
And this is the code (running in an Activity):
private void takeScreenshot() {
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
try {
// image naming and path to include sd card appending name you choose for file
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
// create bitmap screen capture
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
File imageFile = new File(mPath);
FileOutputStream outputStream = new FileOutputStream(imageFile);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
openScreenshot(imageFile);
} catch (Throwable e) {
// Several error may come out with file handling or OOM
e.printStackTrace();
}
}
And this is how you can open the recently generated image:
private void openScreenshot(File imageFile) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(imageFile);
intent.setDataAndType(uri, "image/*");
startActivity(intent);
}
to exclude the button, you can make button hide and then take screen show after some time interval.
I'm new to Java and Android programming and I'm working on a soundboard app.
By the moment the app plays a sound when you click on a button, but I also want to add a sharing functionality for every sound (using OnLongClick), but I just can't make it work.
I've been looking for a solution through the Internet for the past two days but there's no way I can solve it.
I'm using shareIntent, and when the user long clicks the button it will display a list of apps you can share the sound (dropbox, bluetooth, whatsapp...).
If I select dropbox, it just uploads a file with no extension, and sharing with Whatsapp won't work and will display this error: "Failed to send, please try again".
My code looks like this:
final int[] buttonIds = { R.id.sound01, R.id.sound02, R.id.sound03,
R.id.sound04, R.id.sound05, R.id.sound06,
R.id.sound07, R.id.sound08, R.id.sound09,
R.id.sound10, R.id.sound11, R.id.sound12 };
final int[] soundIds = { R.raw.sound01, R.raw.sound02, R.raw.sound03,
R.raw.sound04, R.raw.sound05, R.raw.sound06,
R.raw.sound07, R.raw.sound08, R.raw.sound09,
R.raw.sound10, R.raw.sound11, R.raw.sound12 };
View.OnLongClickListener listener2 = new View.OnLongClickListener()
{
#Override
public boolean onLongClick(View v)
{
for(int i = 0; i < buttonIds.length; i++)
{
if(v.getId() == buttonIds[i])
{
selectedSoundId = soundIds[i];
// Can't share audio. It shares it with no format, so whatsapp won't accept it
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("audio/mp3");
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("android.resource://com.guillefix.zombie_soundboard/" + selectedSoundId));
startActivity(Intent.createChooser(shareIntent, "Send to:"));
break;
}
}
return false;
}
};
Declare Intent Filter in Manifest
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="audio/*" />
</intent-filter>