IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Proč se neudělá screenshot po kliknutí na tlačítko floating widget, které je spojeno s funkcí screenshotu?

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Mirek Veselý:15.10.2023 17:28

Dělám program, který po kliknutí na floating widget vytvoří snímek obrazovky. Opravil jsem všechny chyby, floating widget se načte po udělení oprávnění. V samostatné aplikaci pro tvorbu screenshotů je také vše v pořádku.

Zkusil jsem ji připojit a vytvořit screenshot k floating widget kódu (ve funkci OnClick ve FloatingWidget­Service.java) a tento program nemá žádné errory, ale screenshot se po kliknutí na tlačítko plovoucího widgetu nevytvoří. Zde je celý kód:

MainActivity.java

package com.example.project4;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        startFloatingWidgetService();
    }

    private void startFloatingWidgetService() {
        Intent intent = new Intent(this, FloatingWidgetService.class);
        startService(intent);
    }
}

FloatingWidget­Service.java

package com.example.project4;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
import android.provider.Settings;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

public class FloatingWidgetService extends Service {

    private WindowManager mWindowManager;
    private View mFloatingWidgetView;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    // Method to request the SYSTEM_ALERT_WINDOW permission
    private void requestOverlayPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
            intent.setData(Uri.parse("package:" + getPackageName()));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
    }

    // Method to create the floating widget
    private void createFloatingWidget() {
        // Inflate the layout for the floating widget
        mFloatingWidgetView = LayoutInflater.from(this).inflate(R.layout.floating_widget_layout,
                null);

        // Initialize the button on the floating widget
        Button button = mFloatingWidgetView.findViewById(R.id.floating_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Handle the button click event
                showTextDialog();
                // You can perform other actions here as needed
            }
        });

        // Initialize the WindowManager
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        // Set up WindowManager.LayoutParams for the floating widget
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );

        // Set the gravity of the floating widget (position on the screen)
        params.gravity = Gravity.BOTTOM | Gravity.END;

        // Add the floating widget to the WindowManager
        mWindowManager.addView(mFloatingWidgetView, params);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        // Check if the permission is granted (only for API level 23 and higher)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
            // You don't have permission to draw overlays, so request it
            requestOverlayPermission();
        } else {
            // Permission is granted, proceed with creating the floating widget
            createFloatingWidget();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mFloatingWidgetView != null && mWindowManager != null) {
            mWindowManager.removeView(mFloatingWidgetView);
        }
    }

    private void showTextDialog() {

    }
}

Myscreenshot.java

package com.example.project4;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;

public class Myscreenshot extends AppCompatActivity {

    private static final int REQUEST_CODE_PERMISSION = 101;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.floating_widget_layout);

        Button screenshotButton = findViewById(R.id.floating_button);
        screenshotButton.setOnClickListener(v -> {
            if (checkPermission()) {
                takeScreenshot();
            } else {
                requestPermission();
            }
        });
    }

    private boolean checkPermission() {
        int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        return permission == PackageManager.PERMISSION_GRANTED;
    }

    private void requestPermission() {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_PERMISSION);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                takeScreenshot();
            } else {
                Toast.makeText(this, "Permission denied. Unable to take screenshot.", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void takeScreenshot() {
        try {
            View rootView = getWindow().getDecorView().getRootView();
            rootView.setDrawingCacheEnabled(true);
            Bitmap bitmap = Bitmap.createBitmap(rootView.getDrawingCache());
            rootView.setDrawingCacheEnabled(false);

            String fileName = "screenshot_" + new Date().getTime() + ".png";
            File screenshotFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), fileName);

            FileOutputStream outputStream = new FileOutputStream(screenshotFile);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
            outputStream.flush();
            outputStream.close();

            Toast.makeText(this, "Screenshot saved: " + screenshotFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, "Error taking screenshot.", Toast.LENGTH_SHORT).show();
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/start_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="ahoj"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

floating_widget_la­yout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <Button
        android:id="@+id/floating_button"
        android:layout_width="wrap_content"
        android:layout_height="33dp"
        android:layout_gravity="end"
        android:background="@android:color/holo_red_light"
        android:text="asdasda"
        android:textColor="#212121" />

</LinearLayout>

Androidmanifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Project4"
        tools:targetApi="31">

        <service
            android:name=".FloatingWidgetService"
            android:enabled="true"
            android:exported="true" />

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
 
Odpovědět
15.10.2023 17:28
Avatar
Matúš Olejník:18.10.2023 15:21

Ahoj, vypíše sa ti aspoň text "Screenshot saved:.." v toaste?

Editováno 18.10.2023 15:22
Nahoru Odpovědět
18.10.2023 15:21
/* I am not sure why this works but it fixes the problem */
Avatar
Odpovídá na Matúš Olejník
Mirek Veselý:24.10.2023 14:42

Ano, ale jen v případě samostatného kódu pro screenshot, u tohoto kombinovaného ne.

 
Nahoru Odpovědět
24.10.2023 14:42
Avatar
Odpovídá na Mirek Veselý
Matúš Olejník:24.10.2023 14:53

A v prípade, že sa toast vypíše tak sa ti screen uloží?

Nahoru Odpovědět
24.10.2023 14:53
/* I am not sure why this works but it fixes the problem */
Avatar
Mirek Veselý:25.10.2023 22:08

Ano, to jsem zkontroloval.

 
Nahoru Odpovědět
25.10.2023 22:08
Avatar
Odpovídá na Mirek Veselý
Matúš Olejník:26.10.2023 10:17

Keďže samotný kód urobí screen a aj sa vypíše toast a kombinovaný kód neurobí screen ale ani sa nevypíše toast a nikdy sa ti neukáže toeast s textom "Error taking screenshot." z toho vyplýva, že pri kombinovanom ti to ani len neskočí do funkcie takeScreenshot. Sú tam miesta, ktoré by to mohli ovplyvniť.

Ak vieš debugovať daj si breakpoint do metódy onRequestPermis­sionsResult, ak nevieš daj si tam napr. ďalšie toasty a skontroluj či tieto podmienky platia

if (requestCode == REQUEST_CODE_PERMISSION) {
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

Prípadne pre lahšiu komunikáciu uprav metódu takto a daj vedieť aké toasty sa ukazali

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    Toast.makeText(this, "aaaaa", Toast.LENGTH_SHORT).show();
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CODE_PERMISSION) {
        Toast.makeText(this, "bbbbb", Toast.LENGTH_SHORT).show();
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "ccccc", Toast.LENGTH_SHORT).show();
            takeScreenshot();
        } else {
            Toast.makeText(this, "Permission denied. Unable to take screenshot.", Toast.LENGTH_SHORT).show();
        }
    }
}
Nahoru Odpovědět
26.10.2023 10:17
/* I am not sure why this works but it fixes the problem */
Avatar
Odpovídá na Matúš Olejník
Mirek Veselý:26.10.2023 11:27

Nedal jsem tam to nejdůležitější. v tom FloatingWidget­Service.java má být:

public void onClick(View v) {
                //Myscreenshot screenshot1 = new Myscreenshot();
                //screenshot1.takeScreenshot();

                System.out.println("hello");

To vypsání hello funguje, jakmile ale odstraním // pro komentář, tak se myScreenshot nezavolá ale vypíše se:
*
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pro­ject4, PID: 30790
java.lang.NullPo­interException: Attempt to invoke virtual method 'java.lang.String android.conten­t.Context.get­PackageName()' on a null object reference*

 
Nahoru Odpovědět
26.10.2023 11:27
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.