diff --git a/Launcher/.gitignore b/Launcher/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/Launcher/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/Launcher/.idea/.gitignore b/Launcher/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/Launcher/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/Launcher/.idea/compiler.xml b/Launcher/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/Launcher/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Launcher/.idea/gradle.xml b/Launcher/.idea/gradle.xml new file mode 100644 index 0000000..ae388c2 --- /dev/null +++ b/Launcher/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/Launcher/.idea/misc.xml b/Launcher/.idea/misc.xml new file mode 100644 index 0000000..8978d23 --- /dev/null +++ b/Launcher/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/Launcher/.idea/vcs.xml b/Launcher/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/Launcher/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Launcher/app/.gitignore b/Launcher/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/Launcher/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/Launcher/app/build.gradle b/Launcher/app/build.gradle new file mode 100644 index 0000000..d32fd66 --- /dev/null +++ b/Launcher/app/build.gradle @@ -0,0 +1,57 @@ +plugins { + id 'com.android.application' +} + +android { + namespace 'com.xixun.launcher' + compileSdk 34 + + defaultConfig { + applicationId "com.xixun.launcher" + minSdk 21 + targetSdk 34 + versionCode 1 + versionName "1" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + buildFeatures { + aidl true + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } +} + +dependencies { + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.github.bumptech.glide:glide:4.11.0' + implementation 'androidx.leanback:leanback:1.0.0' + implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25' + implementation files('libs/gnph.jar') + implementation 'com.google.android.material:material:1.8.0' +} + +def getAppName() { + def stringsFile = android.sourceSets.main.res.sourceFiles.find { it.name.equals 'strings.xml' } + String s = new XmlParser().parse(stringsFile).string.find { it.@name.equals 'app_name' }.text(); + return s.replaceAll("\"", ""); +} + +// 修改 Apk 名 +android.applicationVariants.configureEach { variant -> + variant.outputs.configureEach { + def fileName = "${getAppName()}-${versionName}.apk" + outputFileName = fileName + } +} diff --git a/Launcher/app/libs/connService2.jar b/Launcher/app/libs/connService2.jar new file mode 100644 index 0000000..9bb1491 Binary files /dev/null and b/Launcher/app/libs/connService2.jar differ diff --git a/Launcher/app/libs/gnph.jar b/Launcher/app/libs/gnph.jar new file mode 100644 index 0000000..49484bf Binary files /dev/null and b/Launcher/app/libs/gnph.jar differ diff --git a/Launcher/app/libs/ijkplayer-arm64-0.8.8.aar b/Launcher/app/libs/ijkplayer-arm64-0.8.8.aar new file mode 100644 index 0000000..105f873 Binary files /dev/null and b/Launcher/app/libs/ijkplayer-arm64-0.8.8.aar differ diff --git a/Launcher/app/libs/ijkplayer-armv7a-0.8.8.aar b/Launcher/app/libs/ijkplayer-armv7a-0.8.8.aar new file mode 100644 index 0000000..d84b81a Binary files /dev/null and b/Launcher/app/libs/ijkplayer-armv7a-0.8.8.aar differ diff --git a/Launcher/app/libs/ijkplayer-java-0.8.8.aar b/Launcher/app/libs/ijkplayer-java-0.8.8.aar new file mode 100644 index 0000000..8224130 Binary files /dev/null and b/Launcher/app/libs/ijkplayer-java-0.8.8.aar differ diff --git a/Launcher/app/libs/xixun_card_settings_1.2.4.jar b/Launcher/app/libs/xixun_card_settings_1.2.4.jar new file mode 100644 index 0000000..0d17c22 Binary files /dev/null and b/Launcher/app/libs/xixun_card_settings_1.2.4.jar differ diff --git a/Launcher/app/libs/zip4j-2.10.0.jar b/Launcher/app/libs/zip4j-2.10.0.jar new file mode 100644 index 0000000..d80d844 Binary files /dev/null and b/Launcher/app/libs/zip4j-2.10.0.jar differ diff --git a/Launcher/app/proguard-rules.pro b/Launcher/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/Launcher/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/Launcher/app/src/main/AndroidManifest.xml b/Launcher/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a2e7bc8 --- /dev/null +++ b/Launcher/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Launcher/app/src/main/java/com/xixun/launcher/MainActivity.java b/Launcher/app/src/main/java/com/xixun/launcher/MainActivity.java new file mode 100644 index 0000000..d4ca0a8 --- /dev/null +++ b/Launcher/app/src/main/java/com/xixun/launcher/MainActivity.java @@ -0,0 +1,234 @@ +package com.xixun.launcher; + +import android.annotation.SuppressLint; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.os.StrictMode; +import android.view.Choreographer; +import android.view.View; +import android.widget.Button; +import android.widget.RelativeLayout; + +import androidx.activity.ComponentActivity; +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import java.util.ArrayList; + +public class MainActivity extends ComponentActivity implements Choreographer.FrameCallback { + + @RequiresApi(api = Build.VERSION_CODES.S) + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + var msg = "==== MainActivity onCreate ==== UI Thread: " + Thread.currentThread().getId(); + Util.println(msg); + + Button btnProg = findViewById(R.id.btnProg); + btnProg.setOnClickListener((View v)->startActivity(new Intent(MainActivity.this, ProgActivity.class))); + + StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build()); + +// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { +// if(! Environment.isExternalStorageManager()) {// android 11 且 不是已经被拒绝 +// Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); +// intent.setData(Uri.parse("package:" + getPackageName())); +// startActivityForResult(intent, 1024); +// } +// } else { + if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED) + init(); + else { + Util.println("---- No permission, Try again ..."); + ActivityCompat.requestPermissions(this, new String[] { + android.Manifest.permission.ACCESS_FINE_LOCATION, + android.Manifest.permission.ACCESS_COARSE_LOCATION, + android.Manifest.permission.BLUETOOTH, + android.Manifest.permission.BLUETOOTH_ADMIN, + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_SCAN, + android.Manifest.permission.WRITE_EXTERNAL_STORAGE, + android.Manifest.permission.READ_EXTERNAL_STORAGE, + android.Manifest.permission.MANAGE_EXTERNAL_STORAGE, + android.Manifest.permission.RECEIVE_BOOT_COMPLETED, + android.Manifest.permission.INTERNET + }, 999); + } +// } + var intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); + intentFilter.addDataScheme("file"); + registerReceiver(new BroadcastReceiver(){ + long lastMs; + @Override + public void onReceive(Context context, Intent intent) { + var path = intent.getData().getPath(); + Util.println("\nMEDIA_MOUNTED path: "+path); + var ms = System.currentTimeMillis(); + if(ms-lastMs<1000) return; + lastMs = ms; + Util.makeText(MainActivity.this, "MEDIA_MOUNTED path: "+path).show(); + } + }, intentFilter); + } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R) return; + Util.println("onActivityResult "+resultCode+" isExternalStorageManager "+Environment.isExternalStorageManager()); + if (requestCode == 1024) { + if(Environment.isExternalStorageManager()) init(); + } + } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + Util.println("onRequestPermissionsResult "+grantResults[0]); + Util.makeText(MainActivity.this, "onRequestPermissionsResult "+grantResults[0]).show(); + if (requestCode == 999 && grantResults[0] == PackageManager.PERMISSION_GRANTED && Util.backImgFile == null) + init(); + } + + ArrayList reces = new ArrayList<>(); + BluetoothDevice mBluetoothDevice; +// BluetoothAdapter bluetoothAdapter; + + @SuppressLint("UnspecifiedRegisterReceiverFlag") + public void init() { + var dir = Build.VERSION.SDK_INT < Build.VERSION_CODES.R ? Environment.getExternalStorageDirectory().getAbsolutePath() + "/Launcher" : getExternalFilesDir(null).getAbsolutePath(); + var msg = "---- dir " + dir; + Util.println(msg); + Util.programsDir = dir + "/programs"; + Util.backImgFile = dir + "/background"; + + IntentFilter filter = new IntentFilter(); + filter.addAction(BluetoothDevice.ACTION_FOUND); + //filter.addAction(BluetoothDevice.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); + BroadcastReceiver rece; + registerReceiver(rece = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + var action = intent.getAction(); + Util.println("\nBluetooth action: " + action); + Util.makeText(MainActivity.this, "Bluetooth action: " + action).show(); + if (BluetoothDevice.ACTION_FOUND.equals(action)) { + mBluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + if (ActivityCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + Util.println("No Permission BLUETOOTH_CONNECT"); + Util.makeText(MainActivity.this, "No Permission BLUETOOTH_CONNECT").show(); + return; + } + Util.println("Device Name: " + mBluetoothDevice.getName() + " Address: " + mBluetoothDevice.getAddress() + " BondState: " + mBluetoothDevice.getBondState()); + if (mBluetoothDevice.getName() == null || !mBluetoothDevice.getName().equals("RCSP")) + return; + if (mBluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE) { + try { + mBluetoothDevice.createBond(); + } catch (Exception e) { + Util.printStackTrace(e); + } + } +// } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { +// int status = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0); +// if (BluetoothAdapter.STATE_ON == status) { +// mBluetoothAdapter.startDiscovery(); +// Log.d(TAG, "mBluetoothAdapter.startDiscovery---STATE_ON"); +// } +// } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { +// if (!isConnected) { +// mBluetoothAdapter.startDiscovery(); +// Log.d(TAG, "mBluetoothAdapter.startDiscovery---ACTION_DISCOVERY_FINISHED"); +// } +// } else if (BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { +// int newState = intent.getExtras().getInt(BluetoothProfile.EXTRA_STATE); +// switch (newState) { +// case BluetoothProfile.STATE_CONNECTING: +// Log.d(TAG, "CONNECTING"); +// Toast.makeText(context, R.string.bluetooth_connecting, Toast.LENGTH_SHORT).show(); +// break; +// case BluetoothProfile.STATE_CONNECTED: +// Log.d(TAG, "CONNECTED"); +// Toast.makeText(context, R.string.bluetooth_connected, Toast.LENGTH_SHORT).show(); +// RcConnectActivity.this.finish(); +// break; +// } + } + } + }, filter); + reces.add(rece); + +// var intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); +// intentFilter.addDataScheme("file"); +// registerReceiver(new BroadcastReceiver() { +// long lastMs; +// +// @Override +// public void onReceive(Context context, Intent intent) { +// var path = intent.getData().getPath(); +// Util.println("\nMEDIA_MOUNTED path: " + path); +// var ms = System.currentTimeMillis(); +// if (ms - lastMs < 1000) return; +// lastMs = ms; +// Util.makeText(MainActivity.this, "MEDIA_MOUNTED path: " + path).show(); +// } +// }, intentFilter); + +// try { +// bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); +// if (bluetoothAdapter == null) { +// Util.println("BluetoothAdapter is Null"); +// Util.makeText(MainActivity.this, "BluetoothAdapter is Null").show(); +// } else { +// Util.println("BluetoothState: " + bluetoothAdapter.getState()); +// if (bluetoothAdapter.isEnabled()) { +// Util.println("startDiscovery"); +// Util.makeText(MainActivity.this, "bluetoothAdapter startDiscovery").show(); +// bluetoothAdapter.startDiscovery(); +// } else { +// Util.println("enable"); +// Util.makeText(MainActivity.this, "bluetoothAdapter enable").show(); +// bluetoothAdapter.enable(); +// } +// } +// } catch (Exception e) { +// Util.printStackTrace(e); +// Util.makeText(this, Util.toStr(e)).show(); +// } + choreographer.postFrameCallback(this); + } + + Choreographer choreographer = Choreographer.getInstance(); + int frameCnt; + + @Override + public void doFrame(long frameTimeNanos) { + choreographer.postFrameCallback(this); + if(--frameCnt > 0) return; + frameCnt = 600; + //System.out.println("root Width: "+root.getWidth()); +// if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { +// Util.println("No Permission BLUETOOTH_SCAN"); +// return; +// } +// Util.println("BluetoothAdapter is Discovering: " + bluetoothAdapter.isDiscovering()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + for(var rece : reces) unregisterReceiver(rece); + } +} \ No newline at end of file diff --git a/Launcher/app/src/main/java/com/xixun/launcher/ProgActivity.java b/Launcher/app/src/main/java/com/xixun/launcher/ProgActivity.java new file mode 100644 index 0000000..0daa372 --- /dev/null +++ b/Launcher/app/src/main/java/com/xixun/launcher/ProgActivity.java @@ -0,0 +1,84 @@ +package com.xixun.launcher; + +import androidx.fragment.app.FragmentActivity; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.GridLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.io.File; + +public class ProgActivity extends FragmentActivity { + + GridLayout _grid; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_prog); + + _grid = findViewById(R.id.grid_layout); + Button btnNew = findViewById(R.id.BtnNew); + btnNew.setOnClickListener((View v)->startActivity(new Intent(ProgActivity.this, ProgEditActi.class))); + + var programsDir = new File(Util.programsDir); + programsDir.mkdirs(); + var progs = programsDir.listFiles(); + File cover; + for(var prog : progs) if(prog.isDirectory() && (cover = new File(prog, "cover.png")).isFile()) add(prog.getName(), cover); + for(int i=0; i<5; i++) { + var vv = new LinearLayout(this); + vv.setOrientation(LinearLayout.VERTICAL); + var imgV = new ImageView(this); + imgV.setImageResource(R.mipmap.ic_launcher); + imgV.setFocusable(true); + var prm = new LinearLayout.LayoutParams(480, 270); + vv.addView(imgV, prm); + var text = new TextView(this); + text.setText("Prog "+i); + vv.addView(text); + + var hhh = new LinearLayout(this); + var btn = new Button(this); + btn.setText("编辑"); + hhh.addView(btn); + + btn = new Button(this); + btn.setText("删除"); + hhh.addView(btn); + + vv.addView(hhh); + + _grid.addView(vv); + } + } + + void add(String name, File cover) { + var item = new LinearLayout(this); + item.setOrientation(LinearLayout.VERTICAL); + var imgV = new ImageView(this); + imgV.setImageURI(Uri.fromFile(cover)); + imgV.setFocusable(true); + item.addView(imgV, new LinearLayout.LayoutParams(480, 270)); + var text = new TextView(this); + text.setText(name); + item.addView(text); + + var hhh = new LinearLayout(this); + var btn = new Button(this); + btn.setText("编辑"); + hhh.addView(btn); + + btn = new Button(this); + btn.setText("删除"); + hhh.addView(btn); + + item.addView(hhh); + _grid.addView(item); + } +} \ No newline at end of file diff --git a/Launcher/app/src/main/java/com/xixun/launcher/ProgEditActi.java b/Launcher/app/src/main/java/com/xixun/launcher/ProgEditActi.java new file mode 100644 index 0000000..2491a42 --- /dev/null +++ b/Launcher/app/src/main/java/com/xixun/launcher/ProgEditActi.java @@ -0,0 +1,230 @@ +package com.xixun.launcher; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.media.MediaMetadataRetriever; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import gnph.util.Arrs; +import gnph.util.IOs; +import gnph.util.JSList; +import gnph.util.JSMap; + +public class ProgEditActi extends FragmentActivity implements View.OnFocusChangeListener { + + LinearLayout _pageList; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_prog_edit); + _pageList = findViewById(R.id.pageList); + + var name = getIntent().getStringExtra("name"); + if(name==null) { + var names = new File(Util.programsDir).list(); + int i=1; + while(Arrs.indexOf(names, name = "新建节目"+i) > -1) i++; + } + var lbTitle = (TextView) findViewById(R.id.lbTitle); + lbTitle.setText(name); + + var btnClose = (Button) findViewById(R.id.btnClose); + btnClose.setOnClickListener((View v)->finish()); + + var btnSave = (Button) findViewById(R.id.btnSave); + btnSave.setOnClickListener((View v)->{ + var pages = new JSList(); + var cnt = _pageList.getChildCount(); + var progDir = new File(Util.programsDir+"/"+lbTitle.getText()); + progDir.mkdirs(); + for(int i=0; i{ + var inte = new Intent(Intent.ACTION_OPEN_DOCUMENT); + inte.setType("*/*"); + startActivityForResult(inte, 111); + _item = (PageItem) v.getParent(); + }); + + var hhh = new LinearLayout(this); + + pageItem.lbIdx = new TextView(this); + pageItem.lbIdx.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); + hhh.addView(pageItem.lbIdx, new LinearLayout.LayoutParams(120, 84)); + + var btn = new Button(this); + btn.setText("✚"); + btn.setOnFocusChangeListener(this); + btn.setOnClickListener((View v)->{ + var item = (LinearLayout) v.getParent().getParent(); + var ppp = (LinearLayout) item.getParent(); + var iii = ppp.indexOfChild(item); + add(iii+1); + }); + hhh.addView(btn, new LinearLayout.LayoutParams(84, 84)); + + btn = new Button(this); + btn.setText("↑"); + hhh.addView(btn, new LinearLayout.LayoutParams(84, 84)); + btn.setOnFocusChangeListener(this); + btn.setOnClickListener((View v)->{ + var item = (LinearLayout) v.getParent().getParent(); + var list = (LinearLayout) item.getParent(); + var iii = list.indexOfChild(item); + list.removeViewAt(iii); + list.addView(item, iii-1); + v.requestFocus(); + var cnt = list.getChildCount(); + for(int i=0; i{ + var item = (LinearLayout) v.getParent().getParent(); + var list = (LinearLayout) item.getParent(); + var iii = list.indexOfChild(item); + list.removeViewAt(iii); + list.addView(item, iii+1); + v.requestFocus(); + var cnt = list.getChildCount(); + for(int i=0; i{ + var item = (LinearLayout) v.getParent().getParent(); + var list = (LinearLayout) item.getParent(); + list.removeView(item); + var cnt = list.getChildCount(); + for(int i=0; i{ + Toast.makeText(getActivity(), "Implement your own in-app search", Toast.LENGTH_LONG).show(); + }); + setOnItemViewClickedListener(new ItemViewClickedListener()); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (null != mBackgroundTimer) { + Log.d(TAG, "onDestroy: " + mBackgroundTimer.toString()); + mBackgroundTimer.cancel(); + } + } + + private final class ItemViewClickedListener implements OnItemViewClickedListener { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) { + if(item instanceof String) { +// if (((String) item).contains(getString(R.string.error_fragment))) { +// Intent intent = new Intent(getActivity(), BrowseErrorActivity.class); +// startActivity(intent); +// } else { +// Toast.makeText(getActivity(), ((String) item), Toast.LENGTH_SHORT).show(); +// } + } + } + } + + private void updateBackground(String uri) { + int width = mMetrics.widthPixels; + int height = mMetrics.heightPixels; + Glide.with(getActivity()) + .load(uri) + .centerCrop() + .error(mDefaultBackground) + .into(new SimpleTarget(width, height) { + @Override + public void onResourceReady(@NonNull Drawable drawable, + @Nullable Transition transition) { + mBackgroundManager.setDrawable(drawable); + } + }); + mBackgroundTimer.cancel(); + } + + private void startBackgroundTimer() { + if (null != mBackgroundTimer) { + mBackgroundTimer.cancel(); + } + mBackgroundTimer = new Timer(); + mBackgroundTimer.schedule(new UpdateBackgroundTask(), BACKGROUND_UPDATE_DELAY); + } + + private class UpdateBackgroundTask extends TimerTask { + + @Override + public void run() { + mHandler.post(new Runnable() { + @Override + public void run() { + updateBackground(mBackgroundUri); + } + }); + } + } + + private class GridItemPresenter extends Presenter { + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent) { + TextView view = new TextView(parent.getContext()); + view.setLayoutParams(new ViewGroup.LayoutParams(200, 200)); + view.setFocusable(true); + view.setFocusableInTouchMode(true); + view.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.default_background)); + view.setTextColor(Color.WHITE); + view.setGravity(Gravity.CENTER); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, Object item) { + ((TextView) viewHolder.view).setText((String) item); + } + + @Override + public void onUnbindViewHolder(ViewHolder viewHolder) { } + } + +} \ No newline at end of file diff --git a/Launcher/app/src/main/java/com/xixun/launcher/Util.java b/Launcher/app/src/main/java/com/xixun/launcher/Util.java new file mode 100644 index 0000000..b500f9c --- /dev/null +++ b/Launcher/app/src/main/java/com/xixun/launcher/Util.java @@ -0,0 +1,44 @@ +package com.xixun.launcher; + +import android.content.Context; +import android.view.Gravity; +import android.widget.Toast; + +import java.io.CharArrayWriter; +import java.io.PrintWriter; + +public class Util { + public static StringBuffer buf = new StringBuffer(); + + public static void println(String msg) { + System.out.println(msg); + if(buf.length()>1000000) buf.replace(0, 100000, ""); + buf.append(msg).append("\n"); + } + public static void printStackTrace(Throwable e) { + println(toStackTrace(e)); + } + + public static String toStr(Throwable e) { + var traces = e.getStackTrace(); + var msg = e.toString(); + for(var trace : traces) if(trace.getClassName().startsWith("com.xixun.launcher.")) { + msg += "\n at "+trace.getFileName()+'.'+trace.getMethodName()+':'+trace.getLineNumber(); + } + return msg; + } + public static String toStackTrace(Throwable e) { + var out = new CharArrayWriter(); + var writer = new PrintWriter(out); + e.printStackTrace(writer); + writer.flush(); + return out.toString(); + } + + public static Toast makeText(Context context, CharSequence text) { + var toast = Toast.makeText(context, text, Toast.LENGTH_LONG); + toast.setGravity(Gravity.TOP | Gravity.LEFT, 0, 0); + return toast; + } + public static String programsDir, backImgFile; +} diff --git a/Launcher/app/src/main/java/gnph/android/LinearBox.java b/Launcher/app/src/main/java/gnph/android/LinearBox.java new file mode 100644 index 0000000..f6606af --- /dev/null +++ b/Launcher/app/src/main/java/gnph/android/LinearBox.java @@ -0,0 +1,36 @@ +package gnph.android; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +public class LinearBox extends LinearLayout { + + public LinearBox(Context context) { + super(context); + } + public LinearBox(ViewGroup box) { + super(box.getContext()); + box.addView(this); + } + + public LinearBox horizontal() { + setOrientation(HORIZONTAL); + return this; + } + public LinearBox vertical() { + setOrientation(VERTICAL); + return this; + } + + public LinearBox addSpacing(int spacing) { + if(getOrientation()==HORIZONTAL) addView(new View(getContext()), new LayoutParams(spacing, 0)); + else addView(new View(getContext()), new LayoutParams(0, spacing)); + return this; + } + public LinearBox addStretch() { + addView(new View(getContext()), new LayoutParams(0, 0,1)); + return this; + } +} diff --git a/Launcher/app/src/main/res/drawable/back.jpg b/Launcher/app/src/main/res/drawable/back.jpg new file mode 100644 index 0000000..8616e64 Binary files /dev/null and b/Launcher/app/src/main/res/drawable/back.jpg differ diff --git a/Launcher/app/src/main/res/drawable/cast.png b/Launcher/app/src/main/res/drawable/cast.png new file mode 100644 index 0000000..b7c7322 Binary files /dev/null and b/Launcher/app/src/main/res/drawable/cast.png differ diff --git a/Launcher/app/src/main/res/drawable/cast2.jpg b/Launcher/app/src/main/res/drawable/cast2.jpg new file mode 100644 index 0000000..eb13d25 Binary files /dev/null and b/Launcher/app/src/main/res/drawable/cast2.jpg differ diff --git a/Launcher/app/src/main/res/drawable/default_background.xml b/Launcher/app/src/main/res/drawable/default_background.xml new file mode 100644 index 0000000..07b0589 --- /dev/null +++ b/Launcher/app/src/main/res/drawable/default_background.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/Launcher/app/src/main/res/drawable/game.png b/Launcher/app/src/main/res/drawable/game.png new file mode 100644 index 0000000..ab513ea Binary files /dev/null and b/Launcher/app/src/main/res/drawable/game.png differ diff --git a/Launcher/app/src/main/res/drawable/game2.jpg b/Launcher/app/src/main/res/drawable/game2.jpg new file mode 100644 index 0000000..ea34fcf Binary files /dev/null and b/Launcher/app/src/main/res/drawable/game2.jpg differ diff --git a/Launcher/app/src/main/res/drawable/ic_launcher_background.xml b/Launcher/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/Launcher/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Launcher/app/src/main/res/drawable/ic_launcher_foreground.xml b/Launcher/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/Launcher/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Launcher/app/src/main/res/drawable/more.png b/Launcher/app/src/main/res/drawable/more.png new file mode 100644 index 0000000..9e8b7d5 Binary files /dev/null and b/Launcher/app/src/main/res/drawable/more.png differ diff --git a/Launcher/app/src/main/res/drawable/more2.jpg b/Launcher/app/src/main/res/drawable/more2.jpg new file mode 100644 index 0000000..b9c8d4f Binary files /dev/null and b/Launcher/app/src/main/res/drawable/more2.jpg differ diff --git a/Launcher/app/src/main/res/drawable/prog.png b/Launcher/app/src/main/res/drawable/prog.png new file mode 100644 index 0000000..cac766d Binary files /dev/null and b/Launcher/app/src/main/res/drawable/prog.png differ diff --git a/Launcher/app/src/main/res/drawable/prog2.jpg b/Launcher/app/src/main/res/drawable/prog2.jpg new file mode 100644 index 0000000..e37d69e Binary files /dev/null and b/Launcher/app/src/main/res/drawable/prog2.jpg differ diff --git a/Launcher/app/src/main/res/drawable/signal.png b/Launcher/app/src/main/res/drawable/signal.png new file mode 100644 index 0000000..cb767e2 Binary files /dev/null and b/Launcher/app/src/main/res/drawable/signal.png differ diff --git a/Launcher/app/src/main/res/drawable/signal2.jpg b/Launcher/app/src/main/res/drawable/signal2.jpg new file mode 100644 index 0000000..6fc0c6f Binary files /dev/null and b/Launcher/app/src/main/res/drawable/signal2.jpg differ diff --git a/Launcher/app/src/main/res/layout/activity_main.xml b/Launcher/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..c8385bd --- /dev/null +++ b/Launcher/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,73 @@ + + + + +