diff --git a/app-indexing/README.md b/app-indexing/README.md index 5369d50eda..c9f3ace475 100644 --- a/app-indexing/README.md +++ b/app-indexing/README.md @@ -1,48 +1,7 @@ Firebase App Indexing Quickstart ============================== -The Firebase App Indexing Android quickstart demonstrates how to get your app to be found in Google Search. +Firebase App Indexing is no longer the recommended way of indexing content for display as suggested results in Google Search App. -Introduction ------------- +Please check the [App Indexing Documentation](https://firebase.google.com/docs/app-indexing) for more details. -- [Read more about Firebase App Indexing](https://firebase.google.com/docs/app-indexing/) - -Getting Started ---------------- - -- [Add Firebase to your Android Project](https://firebase.google.com/docs/android/setup). -- Open the App Indexing project in Android Studio. -- Run the sample on your Android device or emulator by issuing the following command using **adb** tool: -`adb shell am start -a android.intent.action.VIEW -d "https://www.example.com/articles/test" com.google.samples.quickstart.appindexing` -- Use ADD STICKERS and CLEAR STICKERS buttons to add and remove stickers from the index. - -Result ------------ - - -Support -------- - -- [Stack Overflow](https://stackoverflow.com/questions/tagged/android-app-indexing) -- [Firebase Support](https://firebase.google.com/support/) - -License -------- - -Copyright 2018 Google, Inc. - -Licensed to the Apache Software Foundation (ASF) under one or more contributor -license agreements. See the NOTICE file distributed with this work for -additional information regarding copyright ownership. The ASF licenses this -file to you under the Apache License, Version 2.0 (the "License"); you may not -use this file except in compliance with the License. You may obtain a copy of -the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -License for the specific language governing permissions and limitations under -the License. diff --git a/app-indexing/app/.gitignore b/app-indexing/app/.gitignore deleted file mode 100644 index 796b96d1c4..0000000000 --- a/app-indexing/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/app-indexing/app/build.gradle b/app-indexing/app/build.gradle deleted file mode 100644 index 6b66c1920d..0000000000 --- a/app-indexing/app/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -plugins { - id 'com.android.application' - id 'kotlin-android' - id 'com.google.gms.google-services' -} - -check.dependsOn 'assembleDebugAndroidTest' - -android { - compileSdkVersion 30 - - defaultConfig { - applicationId "com.google.samples.quickstart.appindexing" - minSdkVersion 18 - targetSdkVersion 30 - versionCode 2 - versionName "1.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - buildFeatures { - viewBinding = true - } -} - -dependencies { - implementation project(":internal:lintchecks") - implementation project(":internal:chooserx") - // [START app_indexing_gradle_dep] - implementation 'com.google.firebase:firebase-appindexing:20.0.0' - // [END app_indexing_gradle_dep] - - implementation 'com.google.android.material:material:1.4.0' - - // Testing - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - androidTestImplementation 'androidx.test:rules:1.4.0' - androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' -} - diff --git a/app-indexing/app/proguard-rules.pro b/app-indexing/app/proguard-rules.pro deleted file mode 100644 index 59d7489c33..0000000000 --- a/app-indexing/app/proguard-rules.pro +++ /dev/null @@ -1,20 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - --keepattributes EnclosingMethod --keepattributes InnerClasses diff --git a/app-indexing/app/src/androidTest/java/com/google/samples/quickstart/appindexing/MainActivityTest.java b/app-indexing/app/src/androidTest/java/com/google/samples/quickstart/appindexing/MainActivityTest.java deleted file mode 100644 index 62330adc93..0000000000 --- a/app-indexing/app/src/androidTest/java/com/google/samples/quickstart/appindexing/MainActivityTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.google.samples.quickstart.appindexing; -/* - * Copyright (C) The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import android.content.Intent; -import android.net.Uri; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.rule.ActivityTestRule; - -import com.google.samples.quickstart.appindexing.java.MainActivity; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withText; - - -@RunWith(AndroidJUnit4.class) -public class MainActivityTest { - - @Rule - public ActivityTestRule rule = - new ActivityTestRule<>(MainActivity.class, true, false /* launchActivity */); - - @Test - public void testDeepLink() { - // Create intent to MainActivity - String link = "http://www.example.com/articles/test"; - Intent linkIntent = new Intent(Intent.ACTION_VIEW) - .setData(Uri.parse(link)) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - rule.launchActivity(linkIntent); - - onView(withText(link)) - .check(matches(isDisplayed())); - } -} diff --git a/app-indexing/app/src/androidTest/java/com/google/samples/quickstart/appindexing/kotlin/MainActivityTest.kt b/app-indexing/app/src/androidTest/java/com/google/samples/quickstart/appindexing/kotlin/MainActivityTest.kt deleted file mode 100644 index 63638c9f16..0000000000 --- a/app-indexing/app/src/androidTest/java/com/google/samples/quickstart/appindexing/kotlin/MainActivityTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.google.samples.quickstart.appindexing.kotlin - -import android.content.Intent -import android.net.Uri -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.matcher.ViewMatchers.isDisplayed -import androidx.test.espresso.matcher.ViewMatchers.withText -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.rule.ActivityTestRule -import com.google.samples.quickstart.appindexing.java.MainActivity -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class MainActivityTest { - - @Rule - var rule = ActivityTestRule(MainActivity::class.java, true, false /* launchActivity */) - - @Test - fun testDeepLink() { - // Create intent to MainActivity - val link = "http://www.example.com/kotlin_articles/test" - val linkIntent = Intent(Intent.ACTION_VIEW) - .setData(Uri.parse(link)) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) - rule.launchActivity(linkIntent) - - onView(withText(link)) - .check(matches(isDisplayed())) - } -} diff --git a/app-indexing/app/src/main/AndroidManifest.xml b/app-indexing/app/src/main/AndroidManifest.xml deleted file mode 100644 index 3fb79c6270..0000000000 --- a/app-indexing/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/EntryChoiceActivity.kt b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/EntryChoiceActivity.kt deleted file mode 100644 index ffe2a1c38e..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/EntryChoiceActivity.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.google.samples.quickstart.appindexing - -import android.content.Intent -import com.firebase.example.internal.BaseEntryChoiceActivity -import com.firebase.example.internal.Choice -import com.google.samples.quickstart.appindexing.java.MainActivity - -class EntryChoiceActivity : BaseEntryChoiceActivity() { - - override fun getChoices(): List { - return listOf( - Choice( - "Java", - "Run the Firebase App Indexing quickstart written in Java.", - Intent(this, MainActivity::class.java)), - Choice( - "Kotlin", - "Run the Firebase App Indexing quickstart written in Kotlin.", - Intent(this, com.google.samples.quickstart.appindexing.kotlin.MainActivity::class.java)) - ) - } -} diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/AppIndexingService.java b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/AppIndexingService.java deleted file mode 100644 index 14064e5fd5..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/AppIndexingService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.google.samples.quickstart.appindexing.java; - -import android.app.IntentService; -import android.content.Intent; - -import com.google.android.gms.tasks.Task; -import com.google.android.gms.tasks.Tasks; - -import com.google.firebase.appindexing.FirebaseAppIndex; - -import java.util.concurrent.ExecutionException; - -public class AppIndexingService extends IntentService { - - public AppIndexingService() { - super("AppIndexingService"); - } - - @Override - protected void onHandleIntent(Intent intent) { - final Task setStickersTask = AppIndexingUtil.setStickers(getApplicationContext(), - FirebaseAppIndex.getInstance(getApplicationContext())); - if (setStickersTask != null) { - try { - Tasks.await(setStickersTask); - } catch (ExecutionException e) { - // setStickersTask failed - } catch (InterruptedException e) { - // this thread was interrupted while waiting for setStickersTask to complete - } - } - } -} diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/AppIndexingUtil.java b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/AppIndexingUtil.java deleted file mode 100644 index a97576de15..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/AppIndexingUtil.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.google.samples.quickstart.appindexing.java; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.util.Log; -import android.widget.Toast; - -import androidx.annotation.NonNull; - -import com.google.android.gms.tasks.OnFailureListener; -import com.google.android.gms.tasks.OnSuccessListener; -import com.google.android.gms.tasks.Task; -import com.google.firebase.appindexing.FirebaseAppIndex; -import com.google.firebase.appindexing.FirebaseAppIndexingInvalidArgumentException; -import com.google.firebase.appindexing.Indexable; -import com.google.firebase.appindexing.builders.Indexables; -import com.google.firebase.appindexing.builders.StickerBuilder; -import com.google.firebase.appindexing.builders.StickerPackBuilder; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * See firebase app indexing api code lab - * https://codelabs.developers.google.com/codelabs/app-indexing/#0 - */ - -public class AppIndexingUtil { - private static final String STICKER_FILENAME_PATTERN = "sticker%s.png"; - private static final String CONTENT_URI_ROOT = - String.format("content://%s/", StickerProvider.class.getName()); - private static final String STICKER_URL_PATTERN = "mystickers://sticker/%s"; - private static final String STICKER_PACK_URL_PATTERN = "mystickers://sticker/pack/%s"; - private static final String STICKER_PACK_NAME = "Local Content Pack"; - private static final String TAG = "AppIndexingUtil"; - public static final String FAILED_TO_CLEAR_STICKERS = "Failed to clear stickers"; - public static final String FAILED_TO_INSTALL_STICKERS = "Failed to install stickers"; - - public static void clearStickers(final Context context, FirebaseAppIndex firebaseAppIndex) { - Task task = firebaseAppIndex.removeAll(); - - task.addOnSuccessListener(new OnSuccessListener() { - @Override - public void onSuccess(Void aVoid) { - Toast.makeText(context, "Successfully cleared stickers", Toast.LENGTH_SHORT).show(); - } - }); - task.addOnFailureListener(new OnFailureListener() { - @Override - public void onFailure(@NonNull Exception e) { - Log.w(TAG, FAILED_TO_CLEAR_STICKERS, e); - Toast.makeText(context, FAILED_TO_CLEAR_STICKERS, Toast.LENGTH_SHORT).show(); - } - }); - } - - public static Task setStickers(final Context context, FirebaseAppIndex firebaseAppIndex) { - try { - List stickers = getIndexableStickers(context); - Indexable stickerPack = getIndexableStickerPack(context); - - List indexables = new ArrayList<>(stickers); - indexables.add(stickerPack); - - Task task = firebaseAppIndex.update( - indexables.toArray(new Indexable[indexables.size()])); - - task.addOnSuccessListener(new OnSuccessListener() { - @Override - public void onSuccess(Void aVoid) { - Toast.makeText(context, "Successfully added stickers", Toast.LENGTH_SHORT) - .show(); - } - }); - - task.addOnFailureListener(new OnFailureListener() { - @Override - public void onFailure(@NonNull Exception e) { - Log.d(TAG, FAILED_TO_INSTALL_STICKERS, e); - Toast.makeText(context, FAILED_TO_INSTALL_STICKERS, Toast.LENGTH_SHORT) - .show(); - } - }); - - return task; - } catch (IOException | FirebaseAppIndexingInvalidArgumentException e) { - Log.e(TAG, "Unable to set stickers", e); - return null; - } - } - - private static Indexable getIndexableStickerPack(Context context) - throws IOException, FirebaseAppIndexingInvalidArgumentException { - List stickerBuilders = getStickerBuilders(context); - File stickersDir = new File(context.getFilesDir(), "stickers"); - - if (!stickersDir.exists() && !stickersDir.mkdirs()) { - throw new IOException("Stickers directory does not exist"); - } - - // Use the last sticker for category image for the sticker pack. - final int lastIndex = stickerBuilders.size() - 1; - final String stickerName = getStickerFilename(lastIndex); - final String imageUrl = getStickerUrl(stickerName); - - StickerPackBuilder stickerPackBuilder = Indexables.stickerPackBuilder() - .setName(STICKER_PACK_NAME) - // Firebase App Indexing unique key that must match an intent-filter. - // (e.g. mystickers://sticker/pack/0) - .setUrl(String.format(STICKER_PACK_URL_PATTERN, lastIndex)) - // Defaults to the first sticker in "hasSticker". Used to select between sticker - // packs so should be representative of the sticker pack. - .setImage(imageUrl) - .setHasSticker(stickerBuilders.toArray(new StickerBuilder[stickerBuilders.size()])) - .setDescription("content description"); - return stickerPackBuilder.build(); - } - - private static List getIndexableStickers(Context context) throws IOException, - FirebaseAppIndexingInvalidArgumentException { - List indexableStickers = new ArrayList<>(); - List stickerBuilders = getStickerBuilders(context); - - for (StickerBuilder stickerBuilder : stickerBuilders) { - stickerBuilder - .setIsPartOf(Indexables.stickerPackBuilder() - .setName(STICKER_PACK_NAME)) - .put("keywords", "tag1", "tag2"); - indexableStickers.add(stickerBuilder.build()); - } - - return indexableStickers; - } - - private static List getStickerBuilders(Context context) throws IOException { - List stickerBuilders = new ArrayList<>(); - int[] stickerColors = new int[] {Color.GREEN, Color.RED, Color.BLUE, - Color.YELLOW, Color.MAGENTA}; - - File stickersDir = new File(context.getFilesDir(), "stickers"); - - if (!stickersDir.exists() && !stickersDir.mkdirs()) { - throw new IOException("Stickers directory does not exist"); - } - - for (int i = 0; i < stickerColors.length; i++) { - String stickerFilename = getStickerFilename(i); - File stickerFile = new File(stickersDir, stickerFilename); - String imageUrl = getStickerUrl(stickerFilename); - writeSolidColorBitmapToFile(stickerFile, stickerColors[i]); - - StickerBuilder stickerBuilder = Indexables.stickerBuilder() - .setName(getStickerFilename(i)) - // Firebase App Indexing unique key that must match an intent-filter - // (e.g. mystickers://sticker/0) - .setUrl(String.format(STICKER_URL_PATTERN, i)) - // http url or content uri that resolves to the sticker - // (e.g. http://www.google.com/sticker.png or content://some/path/0) - .setImage(imageUrl) - .setDescription("content description") - .setIsPartOf(Indexables.stickerPackBuilder() - .setName(STICKER_PACK_NAME)) - .put("keywords", "tag1", "tag2"); - stickerBuilders.add(stickerBuilder); - } - - return stickerBuilders; - } - - private static String getStickerFilename(int index) { - return String.format(STICKER_FILENAME_PATTERN, index); - } - - private static String getStickerUrl(String filename) { - return CONTENT_URI_ROOT + filename; - } - - /** - * Writes a simple bitmap to local storage. The image is a solid color with size 400x400 - */ - private static void writeSolidColorBitmapToFile(File file, int color) throws IOException { - if (!file.exists()) { - Bitmap bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888); - bitmap.eraseColor(color); - - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); - } finally { - if (fos != null) { - fos.close(); - } - } - } - } -} diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/MainActivity.java b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/MainActivity.java deleted file mode 100644 index e98cd2ce6e..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/MainActivity.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2014 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.samples.quickstart.appindexing.java; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; - -import com.google.android.gms.tasks.OnFailureListener; -import com.google.android.gms.tasks.OnSuccessListener; -import com.google.android.gms.tasks.Task; -// [START import_classes] -import com.google.firebase.appindexing.FirebaseAppIndex; -import com.google.firebase.appindexing.FirebaseUserActions; -import com.google.firebase.appindexing.Indexable; -import com.google.firebase.appindexing.builders.Actions; -// [END import_classes] -import com.google.samples.quickstart.appindexing.R; -import com.google.samples.quickstart.appindexing.databinding.ActivityMainBinding; - -public class MainActivity extends AppCompatActivity { - - private static final String TAG = MainActivity.class.getName(); - // Define a title for your current page, shown in autocompletion UI - private static final String TITLE = "Sample Article"; - private String articleId; - - // [START handle_intent] - @Override - protected void onCreate(Bundle savedInstanceState) { - // [START_EXCLUDE] - super.onCreate(savedInstanceState); - ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater()); - setContentView(binding.getRoot()); - - final FirebaseAppIndex firebaseAppIndex = FirebaseAppIndex.getInstance(this); - - binding.addStickersBtn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - startService(new Intent(MainActivity.this, AppIndexingService.class)); - } - }); - binding.clearStickersBtn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - AppIndexingUtil.clearStickers(MainActivity.this, firebaseAppIndex); - } - }); - // [END_EXCLUDE] - onNewIntent(getIntent()); - } - - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - String action = intent.getAction(); - Uri data = intent.getData(); - if (Intent.ACTION_VIEW.equals(action) && data != null) { - articleId = data.getLastPathSegment(); - TextView linkText = findViewById(R.id.link); - linkText.setText(data.toString()); - } - } - // [END handle_intent] - - // [START app_indexing_view] - @Override - public void onStart() { - super.onStart(); - if (articleId == null) return; - final Uri BASE_URL = Uri.parse("https://www.example.com/articles/"); - final String APP_URI = BASE_URL.buildUpon().appendPath(articleId).build().toString(); - - Indexable articleToIndex = new Indexable.Builder() - .setName(TITLE) - .setUrl(APP_URI) - .build(); - - Task task = FirebaseAppIndex.getInstance(this).update(articleToIndex); - - // If the Task is already complete, a call to the listener will be immediately - // scheduled - task.addOnSuccessListener(MainActivity.this, new OnSuccessListener() { - @Override - public void onSuccess(Void aVoid) { - Log.d(TAG, "App Indexing API: Successfully added " + TITLE + " to index"); - } - }); - - task.addOnFailureListener(MainActivity.this, new OnFailureListener() { - @Override - public void onFailure(@NonNull Exception exception) { - Log.e(TAG, "App Indexing API: Failed to add " + TITLE + " to index. " + exception - .getMessage()); - } - }); - - // log the view action - Task actionTask = FirebaseUserActions.getInstance(this).start(Actions.newView(TITLE, - APP_URI)); - - actionTask.addOnSuccessListener(MainActivity.this, new OnSuccessListener() { - @Override - public void onSuccess(Void aVoid) { - Log.d(TAG, "App Indexing API: Successfully started view action on " + TITLE); - } - }); - - actionTask.addOnFailureListener(MainActivity.this, new OnFailureListener() { - @Override - public void onFailure(@NonNull Exception exception) { - Log.e(TAG, "App Indexing API: Failed to start view action on " + TITLE + ". " - + exception.getMessage()); - } - }); - } - - @Override - public void onStop() { - super.onStop(); - - if (articleId == null) return; - final Uri BASE_URL = Uri.parse("https://www.example.com/articles/"); - final String APP_URI = BASE_URL.buildUpon().appendPath(articleId).build().toString(); - - Task actionTask = FirebaseUserActions.getInstance(this).end(Actions.newView(TITLE, - APP_URI)); - - actionTask.addOnSuccessListener(MainActivity.this, new OnSuccessListener() { - @Override - public void onSuccess(Void aVoid) { - Log.d(TAG, "App Indexing API: Successfully ended view action on " + TITLE); - } - }); - - actionTask.addOnFailureListener(MainActivity.this, new OnFailureListener() { - @Override - public void onFailure(@NonNull Exception exception) { - Log.e(TAG, "App Indexing API: Failed to end view action on " + TITLE + ". " - + exception.getMessage()); - } - }); - } - // [END app_indexing_view] -} diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/StickerProvider.java b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/StickerProvider.java deleted file mode 100644 index d597e1905e..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/java/StickerProvider.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.google.samples.quickstart.appindexing.java; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.webkit.MimeTypeMap; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * Provider that makes the stickers queryable by other applications. - */ -public class StickerProvider extends ContentProvider { - @Nullable - private File mRootDir; - - @Override - public boolean onCreate() { - final Context context = getContext(); - if (context != null) { - mRootDir = new File(context.getFilesDir(), "stickers"); - try { - mRootDir = mRootDir.getCanonicalFile(); - } catch (IOException e) { - mRootDir = null; - } - } - return mRootDir != null; - } - - @Nullable - @Override - public String getType(@NonNull Uri uri) { - final File file = uriToFile(uri); - if (!isFileInRoot(file)) { - throw new SecurityException("File is not in root: " + file); - } - return getMimeType(file); - } - - @Nullable - @Override - public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) - throws FileNotFoundException { - final File file = uriToFile(uri); - if (!isFileInRoot(file)) { - throw new SecurityException("File is not in root: " + file); - } - return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); - } - - private File uriToFile(@NonNull Uri uri) { - if (mRootDir == null) { - throw new IllegalStateException("Root directory is null"); - } - File file = new File(mRootDir, uri.getEncodedPath()); - try { - file = file.getCanonicalFile(); - } catch (IOException e) { - throw new IllegalArgumentException("Failed to get canonical file: " + file); - } - return file; - } - - private boolean isFileInRoot(@NonNull File file) { - return mRootDir != null && file.getPath().startsWith(mRootDir.getPath()); - } - - private String getMimeType(@NonNull File file) { - String mimeType = null; - final String extension = getFileExtension(file); - if (extension != null) { - mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - } - if (mimeType == null) { - mimeType = "application/octet-stream"; - } - return mimeType; - } - - @Nullable - private String getFileExtension(@NonNull File file) { - String extension = null; - final String filename = file.getName(); - final int index = filename.lastIndexOf('.'); - if (index >= 0) { - extension = filename.substring(index + 1); - } - return extension; - } - - @Nullable - @Override - public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, - @Nullable String[] selectionArgs, @Nullable String sortOrder) { - throw new UnsupportedOperationException("no queries"); - } - - @Nullable - @Override - public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { - throw new UnsupportedOperationException("no inserts"); - } - - @Override - public int delete(@NonNull Uri uri, @Nullable String selection, - @Nullable String[] selectionArgs) { - throw new UnsupportedOperationException("no deletes"); - } - - @Override - public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, - @Nullable String[] selectionArgs) { - throw new UnsupportedOperationException("no updates"); - } -} diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/AppIndexingService.kt b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/AppIndexingService.kt deleted file mode 100644 index ba9839710d..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/AppIndexingService.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.google.samples.quickstart.appindexing.kotlin - -import android.app.IntentService -import android.content.Intent -import com.google.firebase.appindexing.FirebaseAppIndex - -class AppIndexingService : IntentService("AppIndexingService") { - - override fun onHandleIntent(intent: Intent?) { - AppIndexingUtil.setStickers(applicationContext, FirebaseAppIndex.getInstance(applicationContext)) - } -} diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/AppIndexingUtil.kt b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/AppIndexingUtil.kt deleted file mode 100644 index 7fffcd7888..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/AppIndexingUtil.kt +++ /dev/null @@ -1,171 +0,0 @@ -package com.google.samples.quickstart.appindexing.kotlin - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Color -import android.util.Log -import android.widget.Toast -import com.google.firebase.appindexing.FirebaseAppIndex -import com.google.firebase.appindexing.FirebaseAppIndexingInvalidArgumentException -import com.google.firebase.appindexing.Indexable -import com.google.firebase.appindexing.builders.Indexables -import com.google.firebase.appindexing.builders.StickerBuilder -import java.io.File -import java.io.FileOutputStream -import java.io.IOException - -/** - * See firebase app indexing api code lab - * https://codelabs.developers.google.com/codelabs/app-indexing/#0 - */ - -object AppIndexingUtil { - private const val STICKER_FILENAME_PATTERN = "sticker%s.png" - private val CONTENT_URI_ROOT = String.format("content://%s/", StickerProvider::class.java.name) - private const val STICKER_URL_PATTERN = "mystickers://sticker/%s" - private const val STICKER_PACK_URL_PATTERN = "mystickers://sticker/pack/%s" - private const val STICKER_PACK_NAME = "Local Content Pack" - private const val TAG = "AppIndexingUtil" - private const val FAILED_TO_CLEAR_STICKERS = "Failed to clear stickers" - private const val FAILED_TO_INSTALL_STICKERS = "Failed to install stickers" - - fun clearStickers(context: Context, firebaseAppIndex: FirebaseAppIndex) { - val task = firebaseAppIndex.removeAll() - - task.addOnSuccessListener { - Toast.makeText(context, "Successfully cleared stickers", Toast.LENGTH_SHORT).show() - } - task.addOnFailureListener { e -> - Log.w(TAG, FAILED_TO_CLEAR_STICKERS, e) - Toast.makeText(context, FAILED_TO_CLEAR_STICKERS, Toast.LENGTH_SHORT).show() - } - } - - fun setStickers(context: Context, firebaseAppIndex: FirebaseAppIndex) { - try { - val stickers = getIndexableStickers(context) - val stickerPack = getIndexableStickerPack(context) - - val indexables = ArrayList(stickers) - indexables.add(stickerPack) - - val task = firebaseAppIndex.update(*indexables.toTypedArray()) - - task.addOnSuccessListener { - Toast.makeText(context, "Successfully added stickers", Toast.LENGTH_SHORT) - .show() - } - - task.addOnFailureListener { e -> - Log.d(TAG, FAILED_TO_INSTALL_STICKERS, e) - Toast.makeText(context, FAILED_TO_INSTALL_STICKERS, Toast.LENGTH_SHORT) - .show() - } - } catch (e: IOException) { - Log.e(TAG, "Unable to set stickers", e) - } catch (e: FirebaseAppIndexingInvalidArgumentException) { - Log.e(TAG, "Unable to set stickers", e) - } - } - - @Throws(IOException::class, FirebaseAppIndexingInvalidArgumentException::class) - private fun getIndexableStickerPack(context: Context): Indexable { - val stickerBuilders = getStickerBuilders(context) - val stickersDir = File(context.filesDir, "stickers") - - if (!stickersDir.exists() && !stickersDir.mkdirs()) { - throw IOException("Stickers directory does not exist") - } - - // Use the last sticker for category image for the sticker pack. - val lastIndex = stickerBuilders.size - 1 - val stickerName = getStickerFilename(lastIndex) - val imageUrl = getStickerUrl(stickerName) - - val stickerPackBuilder = Indexables.stickerPackBuilder() - .setName(STICKER_PACK_NAME) - // Firebase App Indexing unique key that must match an intent-filter. - // (e.g. mystickers://sticker/pack/0) - .setUrl(String.format(STICKER_PACK_URL_PATTERN, lastIndex)) - // Defaults to the first sticker in "hasSticker". Used to select between sticker - // packs so should be representative of the sticker pack. - .setImage(imageUrl) - .setHasSticker(*stickerBuilders.toTypedArray()) - .setDescription("content description") - return stickerPackBuilder.build() - } - - @Throws(IOException::class, FirebaseAppIndexingInvalidArgumentException::class) - private fun getIndexableStickers(context: Context): List { - val indexableStickers = arrayListOf() - val stickerBuilders = getStickerBuilders(context) - - for (stickerBuilder in stickerBuilders) { - stickerBuilder - .setIsPartOf(Indexables.stickerPackBuilder() - .setName(STICKER_PACK_NAME)) - .put("keywords", "tag1", "tag2") - indexableStickers.add(stickerBuilder.build()) - } - - return indexableStickers - } - - @Throws(IOException::class) - private fun getStickerBuilders(context: Context): List { - val stickerBuilders = arrayListOf() - val stickerColors = intArrayOf(Color.GREEN, Color.RED, Color.BLUE, Color.YELLOW, Color.MAGENTA) - - val stickersDir = File(context.filesDir, "stickers") - - if (!stickersDir.exists() && !stickersDir.mkdirs()) { - throw IOException("Stickers directory does not exist") - } - - for (i in stickerColors.indices) { - val stickerFilename = getStickerFilename(i) - val stickerFile = File(stickersDir, stickerFilename) - val imageUrl = getStickerUrl(stickerFilename) - writeSolidColorBitmapToFile(stickerFile, stickerColors[i]) - - val stickerBuilder = Indexables.stickerBuilder() - .setName(getStickerFilename(i)) - // Firebase App Indexing unique key that must match an intent-filter - // (e.g. mystickers://sticker/0) - .setUrl(String.format(STICKER_URL_PATTERN, i)) - // http url or content uri that resolves to the sticker - // (e.g. http://www.google.com/sticker.png or content://some/path/0) - .setImage(imageUrl) - .setDescription("content description") - .setIsPartOf(Indexables.stickerPackBuilder() - .setName(STICKER_PACK_NAME)) - .put("keywords", "tag1", "tag2") - stickerBuilders.add(stickerBuilder) - } - - return stickerBuilders - } - - private fun getStickerFilename(index: Int) = String.format(STICKER_FILENAME_PATTERN, index) - - private fun getStickerUrl(filename: String) = CONTENT_URI_ROOT + filename - - /** - * Writes a simple bitmap to local storage. The image is a solid color with size 400x400 - */ - @Throws(IOException::class) - private fun writeSolidColorBitmapToFile(file: File, color: Int) { - if (!file.exists()) { - val bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888) - bitmap.eraseColor(color) - - var fos: FileOutputStream? = null - try { - fos = FileOutputStream(file) - bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos) - } finally { - fos?.close() - } - } - } -} diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/MainActivity.kt b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/MainActivity.kt deleted file mode 100644 index 7fe2a8757b..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/MainActivity.kt +++ /dev/null @@ -1,121 +0,0 @@ -package com.google.samples.quickstart.appindexing.kotlin - -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.util.Log -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -// [START import_classes] -import com.google.firebase.appindexing.FirebaseAppIndex -import com.google.firebase.appindexing.FirebaseUserActions -import com.google.firebase.appindexing.Indexable -import com.google.firebase.appindexing.builders.Actions -// [END import_classes] -import com.google.samples.quickstart.appindexing.databinding.ActivityMainBinding - -class MainActivity : AppCompatActivity() { - - private var articleId: String? = null - private lateinit var binding: ActivityMainBinding - private lateinit var linkText: TextView - - // [START handle_intent] - override fun onCreate(savedInstanceState: Bundle?) { - // [START_EXCLUDE] - super.onCreate(savedInstanceState) - binding = ActivityMainBinding.inflate(layoutInflater) - setContentView(binding.root) - - val firebaseAppIndex = FirebaseAppIndex.getInstance(this) - - with(binding) { - addStickersBtn.setOnClickListener { startService(Intent(baseContext, AppIndexingService::class.java)) } - - clearStickersBtn.setOnClickListener { AppIndexingUtil.clearStickers(baseContext, firebaseAppIndex) } - } - linkText = binding.link - - // [END_EXCLUDE] - onNewIntent(intent) - } - - override fun onNewIntent(intent: Intent) { - super.onNewIntent(intent) - val action = intent.action - val data = intent.data - if (Intent.ACTION_VIEW == action && data != null) { - articleId = data.lastPathSegment - linkText.text = data.toString() - } - } - // [END handle_intent] - - // [START app_indexing_view] - public override fun onStart() { - super.onStart() - - if (articleId == null) { - return - } - - val baseUrl = Uri.parse("https://www.example.com/kotlin_articles/") - val appUri = baseUrl.buildUpon().appendPath(articleId).build().toString() - - val articleToIndex = Indexable.Builder() - .setName(TITLE) - .setUrl(appUri) - .build() - - val task = FirebaseAppIndex.getInstance(this).update(articleToIndex) - - // If the Task is already complete, a call to the listener will be immediately - // scheduled - task.addOnSuccessListener(this) { Log.d(TAG, "App Indexing API: Successfully added $TITLE to index") } - - task.addOnFailureListener(this) { exception -> - Log.e(TAG, "App Indexing API: Failed to add $TITLE to index. ${exception.message}") - } - - // log the view action - val actionTask = FirebaseUserActions.getInstance(this).start(Actions.newView(TITLE, - appUri)) - - actionTask.addOnSuccessListener(this) { - Log.d(TAG, "App Indexing API: Successfully started view action on $TITLE") - } - - actionTask.addOnFailureListener(this) { exception -> - Log.e(TAG, "App Indexing API: Failed to start view action on $TITLE. ${exception.message}") - } - } - - public override fun onStop() { - super.onStop() - if (articleId == null) { - return - } - - val baseUrl = Uri.parse("https://www.example.com/kotlin_articles/") - val appUri = baseUrl.buildUpon().appendPath(articleId).build().toString() - - val actionTask = FirebaseUserActions.getInstance(this).end(Actions.newView(TITLE, - appUri)) - - actionTask.addOnSuccessListener(this) { - Log.d(TAG, "App Indexing API: Successfully ended view action on $TITLE") - } - - actionTask.addOnFailureListener(this) { exception -> - Log.e(TAG, "App Indexing API: Failed to end view action on $TITLE. ${exception.message}") - } - } - // [END app_indexing_view] - - companion object { - - private val TAG = MainActivity::class.java.name - // Define a title for your current page, shown in autocompletion UI - private const val TITLE = "Sample Article" - } -} diff --git a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/StickerProvider.kt b/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/StickerProvider.kt deleted file mode 100644 index 7ac0e10ff3..0000000000 --- a/app-indexing/app/src/main/java/com/google/samples/quickstart/appindexing/kotlin/StickerProvider.kt +++ /dev/null @@ -1,114 +0,0 @@ -package com.google.samples.quickstart.appindexing.kotlin - -import android.content.ContentProvider -import android.content.ContentValues -import android.database.Cursor -import android.net.Uri -import android.os.ParcelFileDescriptor -import android.webkit.MimeTypeMap -import java.io.File -import java.io.FileNotFoundException -import java.io.IOException - -/** - * Provider that makes the stickers queryable by other applications. - */ -class StickerProvider : ContentProvider() { - - private lateinit var rootDir: File - - override fun onCreate(): Boolean { - rootDir = File(context?.filesDir, "stickers") - return try { - rootDir = rootDir.canonicalFile - true - } catch (e: IOException) { - false - } - } - - override fun getType(uri: Uri): String? { - val file = uriToFile(uri) - if (!isFileInRoot(file)) { - throw SecurityException("File is not in root: $file") - } - return getMimeType(file) - } - - @Throws(FileNotFoundException::class) - override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? { - val file = uriToFile(uri) - if (!isFileInRoot(file)) { - throw SecurityException("File is not in root: $file") - } - return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY) - } - - private fun uriToFile(uri: Uri): File { - var file = File(rootDir, uri.encodedPath) - try { - file = file.canonicalFile - } catch (e: IOException) { - throw IllegalArgumentException("Failed to get canonical file: $file") - } - - return file - } - - private fun isFileInRoot(file: File): Boolean { - return file.path.startsWith(rootDir.path) - } - - private fun getMimeType(file: File): String { - var mimeType: String? = null - val extension = getFileExtension(file) - if (extension != null) { - mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) - } - if (mimeType == null) { - mimeType = "application/octet-stream" - } - return mimeType - } - - private fun getFileExtension(file: File): String? { - var extension: String? = null - val filename = file.name - val index = filename.lastIndexOf('.') - if (index >= 0) { - extension = filename.substring(index + 1) - } - return extension - } - - override fun query( - uri: Uri, - projection: Array?, - selection: String?, - selectionArgs: Array?, - sortOrder: String? - ): Cursor? { - throw UnsupportedOperationException("no queries") - } - - override fun insert(uri: Uri, values: ContentValues?): Uri? { - throw UnsupportedOperationException("no inserts") - } - - override fun delete( - uri: Uri, - selection: String?, - selectionArgs: Array? - ): Int { - throw UnsupportedOperationException("no deletes") - } - - override fun update( - uri: Uri, - values: ContentValues?, - selection: String?, - selectionArgs: Array? - ): Int { - throw UnsupportedOperationException("no updates") - } -} diff --git a/app-indexing/app/src/main/res/drawable-hdpi/firebase_lockup_400.png b/app-indexing/app/src/main/res/drawable-hdpi/firebase_lockup_400.png deleted file mode 100644 index 2eb21fecd1..0000000000 Binary files a/app-indexing/app/src/main/res/drawable-hdpi/firebase_lockup_400.png and /dev/null differ diff --git a/app-indexing/app/src/main/res/drawable-mdpi/firebase_lockup_400.png b/app-indexing/app/src/main/res/drawable-mdpi/firebase_lockup_400.png deleted file mode 100644 index ffed5b1825..0000000000 Binary files a/app-indexing/app/src/main/res/drawable-mdpi/firebase_lockup_400.png and /dev/null differ diff --git a/app-indexing/app/src/main/res/drawable-xhdpi/firebase_lockup_400.png b/app-indexing/app/src/main/res/drawable-xhdpi/firebase_lockup_400.png deleted file mode 100644 index 78a4a2780f..0000000000 Binary files a/app-indexing/app/src/main/res/drawable-xhdpi/firebase_lockup_400.png and /dev/null differ diff --git a/app-indexing/app/src/main/res/drawable-xxhdpi/firebase_lockup_400.png b/app-indexing/app/src/main/res/drawable-xxhdpi/firebase_lockup_400.png deleted file mode 100644 index 4380835f6a..0000000000 Binary files a/app-indexing/app/src/main/res/drawable-xxhdpi/firebase_lockup_400.png and /dev/null differ diff --git a/app-indexing/app/src/main/res/drawable-xxxhdpi/watermark.png b/app-indexing/app/src/main/res/drawable-xxxhdpi/watermark.png deleted file mode 100644 index 45f1575d24..0000000000 Binary files a/app-indexing/app/src/main/res/drawable-xxxhdpi/watermark.png and /dev/null differ diff --git a/app-indexing/app/src/main/res/layout/activity_main.xml b/app-indexing/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 4113746836..0000000000 --- a/app-indexing/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - -