diff options
Diffstat (limited to 'app/src')
43 files changed, 838 insertions, 0 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2d010dd --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.javispedro.wallmotion"> + + <uses-feature + android:name="android.software.live_wallpaper" + android:required="true" /> + + <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"> + + <service + android:name=".WallService" + android:permission="android.permission.BIND_WALLPAPER"> + <intent-filter> + <action android:name="android.service.wallpaper.WallpaperService" /> + </intent-filter> + <meta-data android:name="android.service.wallpaper" + android:resource="@xml/wallpaper" /> + </service> + + <activity + android:name=".SettingsActivity" + android:label="@string/title_activity_settings" + android:exported="true"> + </activity> + + <activity + android:name=".MainActivity" + android:label="@string/app_name" + android:theme="@style/AppTheme.NoActionBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest>
\ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png Binary files differnew file mode 100644 index 0000000..c80c1c7 --- /dev/null +++ b/app/src/main/ic_launcher-web.png diff --git a/app/src/main/java/com/javispedro/wallmotion/MainActivity.java b/app/src/main/java/com/javispedro/wallmotion/MainActivity.java new file mode 100644 index 0000000..c6859ae --- /dev/null +++ b/app/src/main/java/com/javispedro/wallmotion/MainActivity.java @@ -0,0 +1,117 @@ +package com.javispedro.wallmotion; + +import android.app.WallpaperManager; +import android.content.ComponentName; +import android.content.Intent; +import android.os.Bundle; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; + +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.Menu; +import android.view.MenuItem; + +public class MainActivity extends AppCompatActivity { + private static final String TAG = "MainActivity"; + + private Renderer renderer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + FloatingActionButton fab = findViewById(R.id.set_wallpaper); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openWallpaperSelector(); + } + }); + + SurfaceView view = findViewById(R.id.wallpaper_view); + view.getHolder().addCallback(new WallpaperViewCallback()); + + renderer = new Renderer(this); + } + + @Override + protected void onDestroy() { + renderer.stop(); + renderer = null; + + super.onDestroy(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + + if (id == R.id.action_settings) { + openSettingsActivity(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + renderer.stop(); + super.onPause(); + } + + private class WallpaperViewCallback implements SurfaceHolder.Callback { + @Override + public void surfaceCreated(SurfaceHolder holder) { + Log.d(TAG, "surfaceCreated"); + renderer.start(holder.getSurface()); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + Log.d(TAG, "surfaceDestroyed"); + renderer.stop(); + } + } + + private void openSettingsActivity() { + Intent intent = new Intent(this, SettingsActivity.class); + startActivity(intent); + } + + private void openWallpaperSelector() { + Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER); + intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, + new ComponentName(this, WallService.class)); + startActivity(intent); + } +} diff --git a/app/src/main/java/com/javispedro/wallmotion/Renderer.java b/app/src/main/java/com/javispedro/wallmotion/Renderer.java new file mode 100644 index 0000000..6730afe --- /dev/null +++ b/app/src/main/java/com/javispedro/wallmotion/Renderer.java @@ -0,0 +1,183 @@ +package com.javispedro.wallmotion; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.SharedPreferences; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; +import android.view.Surface; + +import androidx.preference.PreferenceManager; + +import java.io.IOException; + +public class Renderer extends ContextWrapper { + private static final String TAG = "Renderer"; + + private SharedPreferences prefs; + private MediaPlayer player; + + private int savedPosition; + + public Renderer(Context context) { + super(context); + + prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.registerOnSharedPreferenceChangeListener(new PrefsListener()); + } + + public boolean isActive() { + return player != null; + } + + public void start(Surface surface) { + preparePlayer(surface); + } + + public void stop() { + if (player != null && player.isPlaying() && shouldSaveRestorePosition()) { + savedPosition = player.getCurrentPosition(); + Log.d(TAG, "storing current position: " + savedPosition + " ms"); + } + releasePlayer(); + } + + public void reset() { + releasePlayer(); + savedPosition = 0; + } + + private class PrefsListener implements SharedPreferences.OnSharedPreferenceChangeListener { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals(getString(R.string.settings_video_file_key))) { + Log.d(TAG, "video file key changed"); + reset(); + } else if (key.equals(getString(R.string.settings_display_restart_key))) { + savedPosition = 0; + } + } + } + + private class PlayerListener implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener { + @Override + public boolean onError(MediaPlayer mp, int what, int extra) { + Log.e(TAG, "MediaPlayer error: " + what + " extra:" + extra); + return false; + } + + @Override + public void onPrepared(MediaPlayer mp) { + Log.d(TAG, "onPrepared"); + if (player != null && !player.isPlaying()) { + Log.d(TAG, "start playing"); + if (savedPosition > 0 && shouldSaveRestorePosition()) { + restorePlayerPosition(); + } + player.start(); + } + } + + @Override + public void onSeekComplete(MediaPlayer mp) { + Log.d(TAG, "onSeekComplete: " + mp.getCurrentPosition() + " ms"); + } + } + + private void preparePlayer(Surface surface) { + releasePlayer(); + + int scaling = getVideoScaling(); + Log.d(TAG, "video scaling mode: " + scaling); + + Uri uri = getVideoFileUri(); + if (uri == null) { + Log.d(TAG, "no video URI: using missing video URI"); + uri = getResourceVideoFileUri(R.raw.video_file_missing); + scaling = MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT; + } + + try { + preparePlayer(surface, uri, scaling); + } catch (Exception ex) { + Log.e(TAG, "Could not open video URI: " + uri.toString() + " : " + ex.toString()); + ex.printStackTrace(); + releasePlayer(); + + uri = getResourceVideoFileUri(R.raw.video_file_error); + scaling = MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT; + + try { + preparePlayer(surface, uri, scaling); + } catch (Exception ex2) { + Log.e(TAG, "Could not open error video URI either: " + ex2.toString()); + ex2.printStackTrace(); + releasePlayer(); + } + } + } + + private void preparePlayer(Surface surface, Uri uri, int scaling) throws IOException { + Log.d(TAG, "creating player"); + player = new MediaPlayer(); + PlayerListener listener = new PlayerListener(); + player.setOnErrorListener(listener); + player.setOnPreparedListener(listener); + player.setOnSeekCompleteListener(listener); + player.setLooping(true); + player.setVolume(0, 0); + player.setSurface(surface); + Log.d(TAG, "setting data source to " + uri.toString()); + player.setDataSource(this, uri); + player.setVideoScalingMode(scaling); + player.prepareAsync(); + } + + private void releasePlayer() { + if (player != null) { + Log.d(TAG, "releasing player"); + player.release(); + player = null; + } + } + + private void restorePlayerPosition() { + Log.d(TAG, "seeking to " + savedPosition + " ms"); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + player.seekTo(savedPosition, MediaPlayer.SEEK_CLOSEST); + } else { + player.seekTo(savedPosition); + } + } + + private Uri getVideoFileUri() { + String new_value = prefs.getString(getString(R.string.settings_video_file_key), null); + if (new_value != null) { + return Uri.parse(new_value); + } else { + return null; + } + } + + private Uri getResourceVideoFileUri(int resId) { + Uri.Builder builder = new Uri.Builder(); + builder.scheme("android.resource").authority(getPackageName()).appendPath(Integer.toString(resId)); + return builder.build(); + } + + private int getVideoScaling() { + String value = prefs.getString(getString(R.string.settings_display_scale_key), null); + if (TextUtils.equals(value, getString(R.string.settings_display_scale_to_fit_with_cropping_key))) { + return MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING; + } else { + return MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT; + } + } + + private boolean shouldSaveRestorePosition() { + return !prefs.getBoolean(getString(R.string.settings_display_restart_key), false); + } +} diff --git a/app/src/main/java/com/javispedro/wallmotion/SettingsActivity.java b/app/src/main/java/com/javispedro/wallmotion/SettingsActivity.java new file mode 100644 index 0000000..6919ea1 --- /dev/null +++ b/app/src/main/java/com/javispedro/wallmotion/SettingsActivity.java @@ -0,0 +1,174 @@ +package com.javispedro.wallmotion; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.provider.OpenableColumns; +import android.text.TextUtils; +import android.util.Log; + +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceManager; + +public class SettingsActivity extends AppCompatActivity { + private static final String TAG = "SettingsActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.settings_activity); + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.settings, new SettingsFragment()) + .commit(); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + } + + @Override + public boolean onSupportNavigateUp() { + onBackPressed(); + return true; + } + + public static class SettingsFragment extends PreferenceFragmentCompat { + private final static int PICK_VIDEO_FILE = 1; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.root_preferences, rootKey); + Preference video_file = findPreference(getString(R.string.settings_video_file_key)); + video_file.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("video/*"); + intent.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); + startActivityForResult(intent, PICK_VIDEO_FILE); + return true; + } + }); + video_file.setSummary(getVideoFileSummary()); + Preference video_file_clear = findPreference(getString(R.string.settings_video_file_clear_key)); + video_file_clear.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + setVideoFile(null); + return true; + } + }); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, + Intent resultData) { + switch (requestCode) { + case PICK_VIDEO_FILE: + if (resultCode == Activity.RESULT_OK && resultData != null) { + Uri uri = resultData.getData(); + setVideoFile(uri); + } + break; + } + } + + private void setVideoFile(Uri uri) { + ContentResolver resolver = getContext().getContentResolver(); + + // First, release any permission request on the current uri + String cur_value = getStringPref(getString(R.string.settings_video_file_key)); + if (!TextUtils.isEmpty(cur_value)) { + Uri cur_uri = Uri.parse(cur_value); + Log.d(TAG, "release persistable uri permission on uri: " + cur_uri.toString()); + try { + resolver.releasePersistableUriPermission(cur_uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } catch (Exception ex) { + Log.w(TAG, "could not release persistable uri permission on uri: " + cur_uri.toString()); + ex.printStackTrace(); + } + } + + // Then, store the new setting + if (uri != null) { + Log.d(TAG, "storing video_file pref uri: " + uri.toString()); + setStringPref(getString(R.string.settings_video_file_key), uri.toString()); + + // Take a persistent permission on it + Log.d(TAG, "take persistable uri permission on uri: " + uri.toString()); + resolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } else { + Log.d(TAG, "clearing video_file pref uri"); + clearPref(getString(R.string.settings_video_file_key)); + } + + // Refresh the UI summary + Preference video_file = findPreference(getString(R.string.settings_video_file_key)); + video_file.setSummary(getVideoFileSummary()); + } + + private String getVideoFileSummary() { + String cur_value = getStringPref(getString(R.string.settings_video_file_key)); + if (!TextUtils.isEmpty(cur_value)) { + ContentResolver resolver = getContext().getContentResolver(); + Uri uri = Uri.parse(cur_value); + String[] projection = {OpenableColumns.DISPLAY_NAME}; + try { + Cursor cursor = resolver.query(uri, projection, null, null, null); + if (cursor != null) { + int col = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); + if (col >= 0 && cursor.moveToFirst()) { + String name = cursor.getString(col); + cursor.close(); + Log.d(TAG, "got video file display_name: " + name); + return name; + } else { + Log.w(TAG, "Could not navigate cursor for URI: " + uri.toString()); + } + cursor.close(); + } else { + Log.w(TAG, "Could not get cursor for URI: " + uri.toString()); + } + } catch (java.lang.SecurityException ex) { + ex.printStackTrace(); + Log.w(TAG, "Security exception while reading URI: " + uri.toString()); + } + return uri.getLastPathSegment(); + } + return getString(R.string.settings_not_set); + } + + protected String getStringPref(String pref) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + return prefs.getString(pref, null); + } + + protected void setStringPref(String pref, String new_value) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + String cur_value = prefs.getString(pref, null); + if (!TextUtils.equals(cur_value, new_value)) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(pref, new_value); + editor.apply(); + } + } + + protected void clearPref(String pref) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + if (prefs.contains(pref)) { + SharedPreferences.Editor editor = prefs.edit(); + editor.remove(pref); + editor.apply(); + } + } + } +}
\ No newline at end of file diff --git a/app/src/main/java/com/javispedro/wallmotion/WallService.java b/app/src/main/java/com/javispedro/wallmotion/WallService.java new file mode 100644 index 0000000..6a004ff --- /dev/null +++ b/app/src/main/java/com/javispedro/wallmotion/WallService.java @@ -0,0 +1,65 @@ +package com.javispedro.wallmotion; + +import android.service.wallpaper.WallpaperService; +import android.util.Log; +import android.view.SurfaceHolder; + +public class WallService extends WallpaperService { + private static final String TAG = "WallService"; + + @Override + public Engine onCreateEngine() { + return new WallpaperEngine(); + } + + private class WallpaperEngine extends Engine { + private static final String TAG = "WallpaperEngine"; + + private Renderer renderer; + + @Override + public void onCreate(SurfaceHolder surfaceHolder) { + Log.d(TAG, "onCreate"); + renderer = new Renderer(WallService.this); + } + + @Override + public void onDestroy() { + Log.d(TAG, "onDestroy"); + renderer.stop(); + renderer = null; + } + + @Override + public void onSurfaceDestroyed(SurfaceHolder holder) { + Log.d(TAG, "onSurfaceDestroyed"); + renderer.stop(); + } + + @Override + public void onSurfaceCreated(SurfaceHolder holder) { + Log.d(TAG, "onSurfaceCreated"); + } + + @Override + public void onSurfaceChanged(SurfaceHolder holder, int format, + int width, int height) { + Log.d(TAG, "onSurfaceChanged"); + } + + @Override + public void onSurfaceRedrawNeeded(SurfaceHolder holder) { + Log.d(TAG, "onSurfaceRedrawNeeded"); + } + + @Override + public void onVisibilityChanged(boolean visible) { + Log.d(TAG, "onVisibilityChanged(visible: " + visible + ")"); + if (visible) { + renderer.start(getSurfaceHolder().getSurface()); + } else { + renderer.stop(); + } + } + } +} diff --git a/app/src/main/res/drawable-anydpi/ic_action_settings.xml b/app/src/main/res/drawable-anydpi/ic_action_settings.xml new file mode 100644 index 0000000..01b2fba --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_action_settings.xml @@ -0,0 +1,11 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="#FFFFFF" + android:alpha="0.8"> + <path + android:fillColor="#FF000000" + android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/> +</vector> diff --git a/app/src/main/res/drawable-anydpi/ic_action_wallpaper.xml b/app/src/main/res/drawable-anydpi/ic_action_wallpaper.xml new file mode 100644 index 0000000..028d51e --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_action_wallpaper.xml @@ -0,0 +1,11 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="#FFFFFF" + android:alpha="0.8"> + <path + android:fillColor="#FF000000" + android:pathData="M4,4h7L11,2L4,2c-1.1,0 -2,0.9 -2,2v7h2L4,4zM10,13l-4,5h12l-3,-4 -2.03,2.71L10,13zM17,8.5c0,-0.83 -0.67,-1.5 -1.5,-1.5S14,7.67 14,8.5s0.67,1.5 1.5,1.5S17,9.33 17,8.5zM20,2h-7v2h7v7h2L22,4c0,-1.1 -0.9,-2 -2,-2zM20,20h-7v2h7c1.1,0 2,-0.9 2,-2v-7h-2v7zM4,13L2,13v7c0,1.1 0.9,2 2,2h7v-2L4,20v-7z"/> +</vector> diff --git a/app/src/main/res/drawable-hdpi/ic_action_settings.png b/app/src/main/res/drawable-hdpi/ic_action_settings.png Binary files differnew file mode 100644 index 0000000..a99894b --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_wallpaper.png b/app/src/main/res/drawable-hdpi/ic_action_wallpaper.png Binary files differnew file mode 100644 index 0000000..941f061 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_wallpaper.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_settings.png b/app/src/main/res/drawable-mdpi/ic_action_settings.png Binary files differnew file mode 100644 index 0000000..69c67dd --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_wallpaper.png b/app/src/main/res/drawable-mdpi/ic_action_wallpaper.png Binary files differnew file mode 100644 index 0000000..740fb8a --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_wallpaper.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_settings.png b/app/src/main/res/drawable-xhdpi/ic_action_settings.png Binary files differnew file mode 100644 index 0000000..3d88a9e --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_wallpaper.png b/app/src/main/res/drawable-xhdpi/ic_action_wallpaper.png Binary files differnew file mode 100644 index 0000000..1547cac --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_wallpaper.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_settings.png b/app/src/main/res/drawable-xxhdpi/ic_action_settings.png Binary files differnew file mode 100644 index 0000000..80e49bb --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_wallpaper.png b/app/src/main/res/drawable-xxhdpi/ic_action_wallpaper.png Binary files differnew file mode 100644 index 0000000..45a7f14 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_wallpaper.png diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..e0b9f70 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,29 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FF000000" + android:pathData="m4,4h7V2H4C2.9,2 2,2.9 2,4v7h2z"/> + <path + android:fillColor="#FF000000" + android:pathData="m20,2h-7v2h7v7h2V4C22,2.9 21.1,2 20,2Z"/> + <path + android:fillColor="#FF000000" + android:pathData="m20,20h-7v2h7c1.1,0 2,-0.9 2,-2v-7h-2z"/> + <path + android:fillColor="#FF000000" + android:pathData="M4,13H2v7c0,1.1 0.9,2 2,2h7V20H4Z"/> + <path + android:pathData="M16.978,4.5339L16.978,6.2133L15.2986,6.2133L15.2986,4.5339L8.5811,4.5339L8.5811,6.2133L6.9017,6.2133L6.9017,4.5339L5.2223,4.5339L5.2223,19.6483h1.6794v-1.6794h1.6794v1.6794h6.7175v-1.6794h1.6794v1.6794h1.6794L18.6573,4.5339ZM8.5811,16.2895L6.9017,16.2895v-1.6794h1.6794zM8.5811,12.9308L6.9017,12.9308v-1.6794h1.6794zM8.5811,9.572L6.9017,9.572L6.9017,7.8927h1.6794zM16.978,16.2895h-1.6794v-1.6794h1.6794zM16.978,12.9308h-1.6794v-1.6794h1.6794zM16.978,9.572L15.2986,9.572L15.2986,7.8927h1.6794z" + android:strokeWidth="0.83968925" + android:fillColor="#000000"/> + <path + android:pathData="m10.061,12.3404 l-3.1593,3.9492h9.478l-2.3695,-3.1593 -1.6034,2.1404z" + android:strokeWidth="0.78983057" + android:fillColor="#ffffff"/> + <path + android:pathData="m14.5593,8.8051c0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 0,0.83 0.67,1.5 1.5,1.5 0.83,0 1.5,-0.67 1.5,-1.5z" + android:fillColor="#ffffff"/> +</vector> diff --git a/app/src/main/res/drawable/ic_logo.xml b/app/src/main/res/drawable/ic_logo.xml new file mode 100644 index 0000000..4eb6d06 --- /dev/null +++ b/app/src/main/res/drawable/ic_logo.xml @@ -0,0 +1,29 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FF000000" + android:pathData="m4,4h7V2H4C2.9,2 2,2.9 2,4v7h2z"/> + <path + android:fillColor="#FF000000" + android:pathData="m20,2h-7v2h7v7h2V4C22,2.9 21.1,2 20,2Z"/> + <path + android:fillColor="#FF000000" + android:pathData="m20,20h-7v2h7c1.1,0 2,-0.9 2,-2v-7h-2z"/> + <path + android:fillColor="#FF000000" + android:pathData="M4,13H2v7c0,1.1 0.9,2 2,2h7V20H4Z"/> + <path + android:pathData="M16.978,4.5339L16.978,6.2133L15.2986,6.2133L15.2986,4.5339L8.5811,4.5339L8.5811,6.2133L6.9017,6.2133L6.9017,4.5339L5.2223,4.5339L5.2223,19.6483h1.6794v-1.6794h1.6794v1.6794h6.7175v-1.6794h1.6794v1.6794h1.6794L18.6573,4.5339ZM8.5811,16.2895L6.9017,16.2895v-1.6794h1.6794zM8.5811,12.9308L6.9017,12.9308v-1.6794h1.6794zM8.5811,9.572L6.9017,9.572L6.9017,7.8927h1.6794zM16.978,16.2895h-1.6794v-1.6794h1.6794zM16.978,12.9308h-1.6794v-1.6794h1.6794zM16.978,9.572L15.2986,9.572L15.2986,7.8927h1.6794z" + android:strokeWidth="0.83968925" + android:fillColor="#000000"/> + <path + android:pathData="m10.061,12.3404 l-3.1593,3.9492h9.478l-2.3695,-3.1593 -1.6034,2.1404z" + android:strokeWidth="0.78983057" + android:fillColor="#ffffff"/> + <path + android:pathData="m14.5593,8.8051c0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 0,0.83 0.67,1.5 1.5,1.5 0.83,0 1.5,-0.67 1.5,-1.5z" + android:fillColor="#ffffff"/> +</vector> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..f195562 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.coordinatorlayout.widget.CoordinatorLayout 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"> + + <SurfaceView + android:id="@+id/wallpaper_view" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <com.google.android.material.appbar.AppBarLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:theme="@style/AppTheme.AppBarOverlay"> + + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + android:background="?attr/colorPrimary" + app:popupTheme="@style/AppTheme.PopupOverlay" /> + + </com.google.android.material.appbar.AppBarLayout> + + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/set_wallpaper" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:layout_margin="@dimen/fab_margin" + app:srcCompat="@drawable/ic_action_wallpaper" /> + +</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml new file mode 100644 index 0000000..de6591a --- /dev/null +++ b/app/src/main/res/layout/settings_activity.xml @@ -0,0 +1,9 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <FrameLayout + android:id="@+id/settings" + android:layout_width="match_parent" + android:layout_height="match_parent" /> +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml new file mode 100644 index 0000000..1f5570a --- /dev/null +++ b/app/src/main/res/menu/menu_main.xml @@ -0,0 +1,11 @@ +<menu 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" + tools:context="com.javispedro.wallmotion.MainActivity"> + <item + android:id="@+id/action_settings" + android:icon="@drawable/ic_action_settings" + android:orderInCategory="100" + android:title="@string/action_settings" + app:showAsAction="ifRoom" /> +</menu> diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_background"/> + <foreground android:drawable="@drawable/ic_launcher_foreground"/> +</adaptive-icon>
\ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_background"/> + <foreground android:drawable="@drawable/ic_launcher_foreground"/> +</adaptive-icon>
\ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..9045b44 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 0000000..3def45d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..78e6f12 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 0000000..c7f9915 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..dd4c9e1 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 0000000..4ee79f8 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..553d0d3 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 0000000..895d9eb --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..5baec4f --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 0000000..c5998f7 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/app/src/main/res/raw/video_file_error.mp4 b/app/src/main/res/raw/video_file_error.mp4 Binary files differnew file mode 100644 index 0000000..64b8c83 --- /dev/null +++ b/app/src/main/res/raw/video_file_error.mp4 diff --git a/app/src/main/res/raw/video_file_missing.mp4 b/app/src/main/res/raw/video_file_missing.mp4 Binary files differnew file mode 100644 index 0000000..050dc56 --- /dev/null +++ b/app/src/main/res/raw/video_file_missing.mp4 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml new file mode 100644 index 0000000..073ac70 --- /dev/null +++ b/app/src/main/res/values/arrays.xml @@ -0,0 +1,11 @@ +<resources> + <!-- Settings display zoom values --> + <string-array name="settings_display_scale_entries"> + <item>Stretch to fit</item> + <item>Scale and crop to fit</item> + </string-array> + <string-array name="settings_display_scale_values"> + <item>@string/settings_display_scale_to_fit_key</item> + <item>@string/settings_display_scale_to_fit_with_cropping_key</item> + </string-array> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..69b2233 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="colorPrimary">#008577</color> + <color name="colorPrimaryDark">#00574B</color> + <color name="colorAccent">#D81B60</color> +</resources> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..59a0b0c --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,3 @@ +<resources> + <dimen name="fab_margin">16dp</dimen> +</resources> diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..2a54660 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_background">#A4A633</color> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..a8111a0 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,26 @@ +<resources> + <string name="app_name">Wallmotion</string> + + <string name="wallpaper_description">Use a video file as wallpaper</string> + + <!-- Main activity --> + <string name="action_settings">Settings</string> + + <!-- Preferences --> + <string name="title_activity_settings">Wallmotion settings</string> + <string name="settings_source_header">Source video</string> + <string name="settings_video_file_key">video_file</string> + <string name="settings_video_file_title">Video file</string> + <string name="settings_video_file_clear_key">video_file_clear</string> + <string name="settings_video_file_clear_title">Reset to (none)</string> + <string name="settings_not_set">(None)</string> + <string name="settings_display_header">Display options</string> + <string name="settings_display_scale_key">scale</string> + <string name="settings_display_scale_title">Scaling</string> + <string name="settings_display_scale_to_fit_key">scale_to_fit</string> + <string name="settings_display_scale_to_fit_with_cropping_key">scale_to_fit_with_cropping</string> + <string name="settings_display_restart_key">restart</string> + <string name="settings_display_restart_title">Restart video on each display</string> + <string name="settings_display_restart_title_on">Video will be restarted every time wallpaper is shown</string> + <string name="settings_display_restart_title_off">Video time will be remembered every time wallpaper is shown</string> +</resources> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..545b9c6 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ +<resources> + + <!-- Base application theme. --> + <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> + <!-- Customize your theme here. --> + <item name="colorPrimary">@color/colorPrimary</item> + <item name="colorPrimaryDark">@color/colorPrimaryDark</item> + <item name="colorAccent">@color/colorAccent</item> + </style> + + <style name="AppTheme.NoActionBar"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> + + <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> + + <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> + +</resources> diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml new file mode 100644 index 0000000..14b05d7 --- /dev/null +++ b/app/src/main/res/xml/root_preferences.xml @@ -0,0 +1,32 @@ +<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"> + + <PreferenceCategory app:title="@string/settings_source_header"> + <Preference + app:key="@string/settings_video_file_key" + app:title="@string/settings_video_file_title" + app:persistent="true" /> + <Preference + app:key="@string/settings_video_file_clear_key" + app:title="@string/settings_video_file_clear_title" + /> + </PreferenceCategory> + + <PreferenceCategory app:title="@string/settings_display_header"> + <ListPreference + app:key="@string/settings_display_scale_key" + app:title="@string/settings_display_scale_title" + app:entries="@array/settings_display_scale_entries" + app:entryValues="@array/settings_display_scale_values" + app:defaultValue="@string/settings_display_scale_to_fit_key" + app:useSimpleSummaryProvider="true" + app:persistent="true" /> + <SwitchPreferenceCompat + app:key="@string/settings_display_restart_key" + app:title="@string/settings_display_restart_title" + app:summaryOn="@string/settings_display_restart_title_on" + app:summaryOff="@string/settings_display_restart_title_off" + app:persistent="true" + /> + </PreferenceCategory> + +</PreferenceScreen> diff --git a/app/src/main/res/xml/wallpaper.xml b/app/src/main/res/xml/wallpaper.xml new file mode 100644 index 0000000..d4af285 --- /dev/null +++ b/app/src/main/res/xml/wallpaper.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" + android:description="@string/wallpaper_description" + android:settingsActivity="com.javispedro.wallmotion.SettingsActivity" + android:thumbnail="@drawable/ic_logo" + /> |