viztushar / stickers-internet

36 stars 9 forks source link

Stickers are disappearing some times when creating packs in runtime #13

Open vrsrohit opened 5 years ago

vrsrohit commented 5 years ago

Hello I am trying to load stickers from server , I am saving them in internal storage and changed the content provider to suit my requirement but the problem here is when I tried to add 5 sticker packs only 2/3 are reflecting correctly in WhatsApp and they are loading very slowly . (sometimes all packs will show in WhatsApp but fail to display stickers if in case it displays stickers when i clear the app from background then they will disappear ) I have taken provider from your code only and made some changes Here I have pasted my ContentProvider. Please Help !!

PS :: I have switched of battery optimisation for the app and tested in 4 different type of mobiles. `package com.dsrtech.whatsappstickers.Whatsapp;

import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.os.Build; import android.os.ParcelFileDescriptor; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.text.TextUtils; import android.util.Log;

import com.dsrtech.whatsappstickers.BuildConfig; import com.dsrtech.whatsappstickers.utils.NewImageSaver;

import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects;

import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;

@RequiresApi(api = Build.VERSION_CODES.KITKAT) public class StickerContentProvider extends ContentProvider {

/**
 * Do not change the strings listed below, as these are used by WhatsApp. And changing these will break the interface between sticker app and WhatsApp.
 */
public static final String STICKER_PACK_IDENTIFIER_IN_QUERY = "sticker_pack_identifier";
public static final String STICKER_PACK_NAME_IN_QUERY = "sticker_pack_name";
public static final String STICKER_PACK_PUBLISHER_IN_QUERY = "sticker_pack_publisher";
public static final String STICKER_PACK_ICON_IN_QUERY = "sticker_pack_icon";
public static final String ANDROID_APP_DOWNLOAD_LINK_IN_QUERY = "https://play.google.com/store/apps/details?id=com.dsrtech.cutpasteeditor&hl=en";
public static final String IOS_APP_DOWNLOAD_LINK_IN_QUERY = "ios_app_download_link";
public static final String PUBLISHER_EMAIL = "sticker_pack_publisher_email";
public static final String PUBLISHER_WEBSITE = "sticker_pack_publisher_website";
public static final String PRIVACY_POLICY_WEBSITE = "sticker_pack_privacy_policy_website";
public static final String LICENSE_AGREENMENT_WEBSITE = "sticker_pack_license_agreement_website";

public static final String STICKER_FILE_NAME_IN_QUERY = "sticker_file_name";
public static final String STICKER_FILE_EMOJI_IN_QUERY = "sticker_emoji";

public static final String CONTENT_SCHEME = "content";
static final String METADATA = "metadata";
static final String STICKERS = "stickers";
static final String STICKERS_ASSET = "stickers_asset";
private static final String TAG = StickerContentProvider.class.getSimpleName();
/**
 * Do not change the values in the UriMatcher because otherwise, WhatsApp will not be able to fetch the stickers from the ContentProvider.
 */
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int METADATA_CODE = 1;
private static final int METADATA_CODE_FOR_SINGLE_PACK = 2;
private static final int STICKERS_CODE = 3;
private static final int STICKERS_ASSET_CODE = 4;
private static final int STICKER_PACK_TRAY_ICON_CODE = 5;
public static Uri AUTHORITY_URI = new Uri.Builder().scheme(StickerContentProvider.CONTENT_SCHEME).authority(BuildConfig.CONTENT_PROVIDER_AUTHORITY).appendPath(StickerContentProvider.METADATA).build();
private List<StickerPack> stickerPackList = new ArrayList<>();
private static final String LOGTAG = "Whatsapp_status";

@Override
public boolean onCreate() {
    final String authority = BuildConfig.CONTENT_PROVIDER_AUTHORITY;
    if (!authority.startsWith(Objects.requireNonNull(getContext()).getPackageName())) {
        throw new IllegalStateException("your authority (" + authority + ") for the content provider should start with your package name: " + getContext().getPackageName());
    }

    //the call to get the metadata for the sticker packs.
    MATCHER.addURI(authority, METADATA, METADATA_CODE);

    //the call to get the metadata for single sticker pack. * represent the identifier
    MATCHER.addURI(authority, METADATA + "/*", METADATA_CODE_FOR_SINGLE_PACK);

    //gets the list of stickers for a sticker pack, * respresent the identifier.
    MATCHER.addURI(authority, STICKERS + "/*", STICKERS_CODE);

    for (StickerPack stickerPack : getStickerPackList()) {
        Log.e(TAG, "onCreate: " + stickerPack.identifier);
        MATCHER.addURI(authority, STICKERS_ASSET + "/" + stickerPack.identifier + "/" + stickerPack.trayImageFile, STICKER_PACK_TRAY_ICON_CODE);
        if (stickerPack.getStickers() != null) {
            for (Sticker sticker : stickerPack.getStickers()) {
                MATCHER.addURI(authority, STICKERS_ASSET + "/" + stickerPack.identifier + "/" + sticker.imageFileName, STICKERS_ASSET_CODE);
            }

        }
    }

    return true;
}

@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, String selection,
                    String[] selectionArgs, String sortOrder) {
    final int code = MATCHER.match(uri);
    Log.d(TAG, "query: " + code + uri);
    if (code == METADATA_CODE) {
        return getPackForAllStickerPacks(uri);
    } else if (code == METADATA_CODE_FOR_SINGLE_PACK) {
        return getCursorForSingleStickerPack(uri);
    } else if (code == STICKERS_CODE) {
        return getStickersForAStickerPack(uri);
    } else {
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
}

@Nullable
@Override
public AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode) {
    MATCHER.match(uri);
    final int matchCode = MATCHER.match(uri);
    final List<String> pathSegments = uri.getPathSegments();
    Log.d(TAG, "openFile: " + matchCode + uri + "\n" + uri.getAuthority()
            + "\n" + pathSegments.get(pathSegments.size() - 3) + "/"
            + "\n" + pathSegments.get(pathSegments.size() - 2) + "/"
            + "\n" + pathSegments.get(pathSegments.size() - 1));

    return getImageAsset(uri);
}

private AssetFileDescriptor getImageAsset(Uri uri) throws IllegalArgumentException {
    final List<String> pathSegments = uri.getPathSegments();
    if (pathSegments.size() != 3) {
        throw new IllegalArgumentException("path segments should be 3, uri is: " + uri);
    }
    String fileName = pathSegments.get(pathSegments.size() - 1);
    final String identifier = pathSegments.get(pathSegments.size() - 2);
    if (TextUtils.isEmpty(identifier)) {
        throw new IllegalArgumentException("identifier is empty, uri: " + uri);
    }
    if (TextUtils.isEmpty(fileName)) {
        throw new IllegalArgumentException("file name is empty, uri: " + uri);
    }
    for (StickerPack stickerPack : getStickerPackList()) {
        if (identifier.equals(stickerPack.identifier)) {
            if (fileName.equals(stickerPack.trayImageFile)) {
                return fetchFile(uri, fileName, identifier);
            } else {
                for (Sticker sticker : stickerPack.getStickers()) {
                    if (fileName.equals(sticker.imageFileName)) {
                        return fetchFile(uri, fileName, identifier);
                    }
                }
            }
        }
    }
    return null;
}

private AssetFileDescriptor fetchFile(@NonNull Uri uri, @NonNull String fileName, @NonNull String identifier) {
    Log.i(LOGTAG," + fetchfile called"+fileName +" + "+ identifier);
    try {
        File file;
        file = new NewImageSaver(getContext()).loadFile("whatsapp_stickers" + identifier, fileName);
        if (!file.exists()) {
            Log.i(LOGTAG," + fetchfile file not exists");
        }
        Log.i(LOGTAG," + fetchfile file exists");
        //working one
        //return new AssetFileDescriptor(ParcelFileDescriptor.open(file, MODE_READ_ONLY), 0L, -1L);
        //edited by me
        return new AssetFileDescriptor(ParcelFileDescriptor.open(file, MODE_READ_ONLY), 0L, file.length());
    } catch (IOException e) {
        Log.e(Objects.requireNonNull(getContext()).getPackageName(), "IOException when getting asset file, uri:" + uri, e);
        return null;
    }
}
@Override
public String getType(@NonNull Uri uri) {
    final int matchCode = MATCHER.match(uri);
    switch (matchCode) {
        case METADATA_CODE:
            return "vnd.android.cursor.dir/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + METADATA;
        case METADATA_CODE_FOR_SINGLE_PACK:
            return "vnd.android.cursor.item/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + METADATA;
        case STICKERS_CODE:
            return "vnd.android.cursor.dir/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + STICKERS;
        case STICKERS_ASSET_CODE:
            return "image/webp";
        case STICKER_PACK_TRAY_ICON_CODE:
            return "image/png";
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
}

public List<StickerPack> getStickerPackList() {
    Log.i(LOGTAG," + getStickerPackList Called");
    stickerPackList.clear();
    for (int i = 1 ; i<=new NewImageSaver(getContext()).loadMainFolderSize();i++ ){
        StickerPack mStickerPack = new StickerPack(String.valueOf(i), "PixelPack"+i, "PixelForce", "tray_Cuppy.png", "", "", "", "");
        ArrayList<Sticker> mStickers = new ArrayList<>();
        List<String> mEmojis = new ArrayList<>();
        String str = getEmojiByUnicode(0x1F60A);
        mEmojis.add(str);
        mEmojis.add(str);

        for (int j = 0; j < new NewImageSaver(getContext()).loadFileNames("whatsapp_stickers"+i).size(); j++) {
            String name = new NewImageSaver(getContext()).loadFileNames("whatsapp_stickers"+i).get(j);
            Log.i(LOGTAG," + getStickerPackList adding sticker + "+name);
            if (!name.equals("tray_Cuppy.png")) {
                mStickers.add(new Sticker(name, mEmojis));
            }
        }
        mStickerPack.setStickers(mStickers);
        stickerPackList.add(mStickerPack);
    }
    Log.i(LOGTAG," + getStickerPackList size + "+stickerPackList.size());
    //stickerPackList.add(new CustomSaverNew().RetriveObject("stickerpack1",getContext(),"stickerpack1"));
    return stickerPackList;

}

public String getEmojiByUnicode(int unicode) {
    return new String(Character.toChars(unicode));
}

private Cursor getPackForAllStickerPacks(@NonNull Uri uri) {
    return getStickerPackInfo(uri, getStickerPackList());
}

private Cursor getCursorForSingleStickerPack(@NonNull Uri uri) {
    final String identifier = uri.getLastPathSegment();
    for (StickerPack stickerPack : getStickerPackList()) {
        if (Objects.requireNonNull(identifier).equals(stickerPack.identifier)) {
            return getStickerPackInfo(uri, Collections.singletonList(stickerPack));
        }
    }

    return getStickerPackInfo(uri, new ArrayList<>());
}

@NonNull
private Cursor getStickerPackInfo(@NonNull Uri uri, @NonNull List<StickerPack> stickerPackList) {
    MatrixCursor cursor = new MatrixCursor(
            new String[]{
                    STICKER_PACK_IDENTIFIER_IN_QUERY,
                    STICKER_PACK_NAME_IN_QUERY,
                    STICKER_PACK_PUBLISHER_IN_QUERY,
                    STICKER_PACK_ICON_IN_QUERY,
                    ANDROID_APP_DOWNLOAD_LINK_IN_QUERY,
                    IOS_APP_DOWNLOAD_LINK_IN_QUERY,
                    PUBLISHER_EMAIL,
                    PUBLISHER_WEBSITE,
                    PRIVACY_POLICY_WEBSITE,
                    LICENSE_AGREENMENT_WEBSITE
            });
    for (StickerPack stickerPack : stickerPackList) {
        MatrixCursor.RowBuilder builder = cursor.newRow();
        builder.add(stickerPack.identifier);
        builder.add(stickerPack.name);
        builder.add(stickerPack.publisher);
        builder.add(stickerPack.trayImageFile);
        builder.add(stickerPack.androidPlayStoreLink);
        builder.add(stickerPack.iosAppStoreLink);
        builder.add(stickerPack.publisherEmail);
        builder.add(stickerPack.publisherWebsite);
        builder.add(stickerPack.privacyPolicyWebsite);
        builder.add(stickerPack.licenseAgreementWebsite);
    }
    Log.d(LOGTAG, "getStickerPackInfo: " + stickerPackList.size());
    cursor.setNotificationUri(Objects.requireNonNull(getContext()).getContentResolver(), uri);
    return cursor;
}

@NonNull
private Cursor getStickersForAStickerPack(@NonNull Uri uri) {
    final String identifier = uri.getLastPathSegment();
    MatrixCursor cursor = new MatrixCursor(new String[]{STICKER_FILE_NAME_IN_QUERY, STICKER_FILE_EMOJI_IN_QUERY});
    for (StickerPack stickerPack : getStickerPackList()) {
        if (Objects.requireNonNull(identifier).equals(stickerPack.identifier)) {
            for (Sticker sticker : stickerPack.getStickers()) {
                cursor.addRow(new Object[]{sticker.imageFileName, TextUtils.join(",", sticker.emojis)});
            }
        }
    }
    cursor.setNotificationUri(Objects.requireNonNull(getContext()).getContentResolver(), uri);
    return cursor;
}

@Override
public int delete(@NonNull Uri uri, @Nullable String selection, String[] selectionArgs) {
    throw new UnsupportedOperationException("Not supported");
}

@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
    throw new UnsupportedOperationException("Not supported");
}

@Override
public int update(@NonNull Uri uri, ContentValues values, String selection,
                  String[] selectionArgs) {
    throw new UnsupportedOperationException("Not supported");
}

} `

viztushar commented 4 years ago

@vrsrohit your ContentProvider provider is not providing file to the whatsapp or check your stickers location is same as your provider location url.